Managing C++ Delegate lifetime - c++

I came across the following blog post which explains how to build C++ delegates using variadic templates: http://blog.coldflake.com/posts/2014-01-12-C++-delegates-on-steroids.html
I'm reproducing the Delegate class in the post here:
template<typename return_type, typename... params>
class Delegate
{
typedef return_type (*Type)(void* callee, params...);
public:
Delegate(void* callee, Type function)
: fpCallee(callee)
, fpCallbackFunction(function) {}
template <class T, return_type (T::*TMethod)(params...)>
static Delegate from_function(T* callee)
{
Delegate d(callee, &methodCaller<T, TMethod>);
return d;
}
return_type operator()(params... xs) const
{
return (*fpCallbackFunction)(fpCallee, xs...);
}
private:
void* fpCallee;
Type fpCallbackFunction;
template <class T, return_type (T::*TMethod)(params...)>
static return_type methodCaller(void* callee, params... xs)
{
T* p = static_cast<T*>(callee);
return (p->*TMethod)(xs...);
}
};
And an example of how to use the class is given here:
class A
{
public:
int foo(int x)
{
return x*x;
}
int bar(int x, int y, char a)
{
return x*y;
}
};
int main()
{
A a;
auto d = Delegate<int, int>::from_function<A, &A::foo>(&a);
auto d2 = Delegate<int, int, int, char>::from_function<A, &A::bar>(&a);
printf("delegate with return value: d(42)=%d\n", d(42));
printf("for d2: d2(42, 2, 'a')=%d\n", d2(42, 2, 'a'));
return 0;
}
The technique is pretty cool, except that I would also like to have the Delegate class manage the callee's lifetime (in other words I would like to instantiate A on the heap and when the Delegate instance is deleted or goes out of scope, it should also be able to delete the callee (the A instance in this case)). Is there a simple way of doing this? Am I missing something? One solution would be to also pass a deleter object, which would cast the void* fpCallee to the correct type and then call delete ont it. Is there a better solution for this?

You could use shared_ptr<void> to store the callee instead of void* (see this question for why this doesn't cause delete problems; thanks Kindread). This would require you to keep every callee in a shared_ptr, but if you don't mind that, it would solve your problem.
And while this isn't an answer to the question, you could accomplish pretty much the same thing using a lambda instead of Delegate:
auto a = std::make_shared<A>();
auto d = [a](int x) { a->foo(x); };

Related

How to Store Variadic Template Arguments Passed into Constructor and then Save them for Later Use?

I am curious how one would go about storing a parameter pack passed into a function and storing the values for later use.
For instance:
class Storage {
public:
template<typename... Args>
Storage(Args... args) {
//store args somehow
}
}
Basically I am trying to make a class like tuple, but where you don't have to specify what types the tuple will hold, you just pass in the values through the constructor.
So for instance instead of doing something like this:
std::tuple<int, std::string> t = std::make_tuple(5, "s");
You could do this:
Storage storage(5, "s");
And this way you could any Storage objects in the same vector or list. And then in the storage class there would be some method like std::get that would return a given index of an element we passed in.
Since run will return void, I assume all the functions you need to wrap can be functions that return void too.
In that case you can do it like this (and let lambda capture do the storing for you):
#include <iostream>
#include <functional>
#include <string>
#include <utility>
class FnWrapper
{
public:
template<typename fn_t, typename... args_t>
FnWrapper(fn_t fn, args_t&&... args) :
m_fn{ [=] { fn(args...); } }
{
}
void run()
{
m_fn();
}
private:
std::function<void()> m_fn;
};
void foo(const std::string& b)
{
std::cout << b;
}
int main()
{
std::string hello{ "Hello World!" };
FnWrapper wrapper{ foo, hello };
wrapper.run();
return 0;
}
OK, what you're asking is type erasure. Typical way of implementing it is via a virtual function inherited by a class template.
Live demo here: https://godbolt.org/z/fddfTEe5M
I stripped all the forwards, references and other boilerplate for brevity. It is not meant to be production code by any means.
#include<memory>
#include <iostream>
#include <stdexcept>
struct Fn
{
Fn() = default;
template<typename F, typename...Arguments>
Fn(F f, Arguments...arguments)
{
callable =
std::make_unique<CallableImpl<F, Arguments...>>(f, arguments...);
}
void operator()()
{
callable
? callable->call()
: throw std::runtime_error("empty function");
}
struct Callable
{
virtual void call() =0;
virtual ~Callable() = default;
};
template<typename T, typename...Args_>
struct CallableImpl : Callable
{
CallableImpl(T f, Args_...args)
: theCallable(f)
, theArgs(std::make_tuple(args...))
{}
T theCallable;
std::tuple<Args_...> theArgs;
void call() override
{
std::apply(theCallable, theArgs);
}
};
std::unique_ptr<Callable> callable{};
};
void f(int a)
{
std::cout << a << '\n';
}
int main(int, char*[])
{
Fn fx{f, 3};
fx();
char x = 'q';
Fn flambda( [x](){std::cerr << x << '\n';} );
flambda();
}
The "meat" of it lies here:
struct Callable
{
virtual void call() =0;
virtual ~Callable() = default;
};
template<typename T, typename...Args_>
struct CallableImpl : Callable
{
CallableImpl(T f, Args_...args)
: theCallable(f)
, theArgs(std::make_tuple(args...))
{}
T theCallable;
std::tuple<Args_...> theArgs;
void call() override
{
std::apply(theCallable, theArgs);
}
};
Callable is just the interface to access the object. Enough to store a pointer to it and access desired methods.
The actual storage happens in its derived classes:template<typename T, typename...Args_> struct CallableImpl : Callable. Note the tuple there.
T is for storing the actual object, whatever it is. Note that it has to implement some for of compile-time interface, in C++ terms referred to as a concept. In that case, it has to be callable with a given set of arguments.
Thus it has to be known upfront.
The outer structure holds the unique_ptr to Callable but is able to instantiate the interface thanks to the templated constructor:
template<typename F, typename...Arguments>
Fn(F f, Arguments...arguments)
{
callable =
std::make_unique<CallableImpl<F, Arguments...>>(f, arguments...);
}
What is the main advantage of it?
When done properly, it has value semantics. Effectively, it can be used to represent a sort of polymorphism without derivation, note T doesn't have to have a common base class, it just has to be callable in one way or another; this can be used for addition, subtraction, printing, whatever.
As for the main drawbacks: a virtual function call (CallableImpl stored as Callable) which may hinder performance. Also, getting back the original type is difficult, if not nearly impossible.

Dangers of storing rvalue references in templates

Consider following piece of code:
#include <functional>
template<class T>
class factory {
public:
factory(T &&t) : t_(std::forward<T>(t)) {}
private:
T &&t_;
};
template<class T>
factory<T> make_factory(T &&t) {
return factory<T>(std::forward<T>(t));
}
int main(){
int i = 3;
auto bar = make_factory(i); //now it will store int &
auto foo = make_factory(5); //now will store int &&
return 0;
}
This is of course simplification of code but shows my general idea - I am considering storing references to rvalues. As far as I know in the first case the deduced type will be int & so the factory will be valid until leaving of the scope (due to reference collapsing). My questions are
Is the foo object causing undefined behaviour?
If not, for how long is the stored rvalue reference valid (I mean, what's its scope)?
Are there any caveats that I am missing?
EDIT:
I thought this is enough but I see I have to clarify. I want to achieve something like this:
template<class T>
class factory {
public:
factory(T &&t) : t_(std::forward<T>(t)) {}
auto make() const & {
return wrap(t_);
}
auto make() && {
return wrap(/*what here, move(t_), forward<T>(t_) ?*/);
}
private:
T t_;//or maybe T&& here?
};
I do not want to copy the member unless I really have to. I would like to do something like forwarding through the factory class.
Generally do this:
template<class T>
class factory {
public:
factory(T &&t) : t_(std::forward<T>(t)) {}
private:
T t_; // could be a lvalue ref
};
and it just works. Really. Yep, that case too.
Rvalues should not outlive their enclosing statement; so your make factory should not return a struct containing an rvalue ref.

Create library to override operator*() of iterator - risk dangling pointer

I am trying to create my own boost::adaptors::transformed.
Here is the related boost code.
Here is its usage (modified from a SO answer by LogicStuff):-
C funcPointer(B& b){
//"funcPointer" is function convert from "B" to "C"
return instance-of-C
}
MyArray<B> test; //<-- any type, must already have begin() & end()
for(C c : test | boost::adaptor::transformed(funcPointer)) {
//... something ....
}
The result will be the same as :-
for(auto b : test) {
C c = funcPointer(b);
//... something ...
}
My Attempt
I created CollectAdapter that aim to work like boost::adaptor::transformed.
It works OK in most common cases.
Here is the full demo and back up. (same as below code)
The problematic part is CollectAdapter - the core of my library.
I don't know whether I should cache the collection_ by-pointer or by-value.
CollectAdapter encapsulates underlying collection_ (e.g. pointer to std::vector<>) :-
template<class COLLECTION,class ADAPTER>class CollectAdapter{
using CollectAdapterT=CollectAdapter<COLLECTION,ADAPTER>;
COLLECTION* collection_; //<---- #1 problem? should cache by value?
ADAPTER adapter_; //<---- = func1 (or func2)
public: CollectAdapter(COLLECTION& collection,ADAPTER adapter){
collection_=&collection;
adapter_=adapter;
}
public: auto begin(){
return IteratorAdapter<
decltype(std::declval<COLLECTION>().begin()),
decltype(adapter_)>
(collection_->begin(),adapter_);
}
public: auto end(){ ..... }
};
IteratorAdapter (used above) encapsulates underlying iterator, change behavior of operator* :-
template<class ITERATORT,class ADAPTER>class IteratorAdapter : public ITERATORT {
ADAPTER adapter_;
public: IteratorAdapter(ITERATORT underlying,ADAPTER adapter) :
ITERATORT(underlying),
adapter_(adapter)
{ }
public: auto operator*(){
return adapter_(ITERATORT::operator*());
}
};
CollectAdapterWidget (used below) is just a helper class to construct CollectAdapter-instance.
It can be used like:-
int func1(int i){ return i+10; }
int main(){
std::vector<int> test; test.push_back(5);
for(auto b:CollectAdapterWidget::createAdapter(test,func1)){
//^ create "CollectAdapter<std::vector<int>,func1>" instance
//here, b=5+10=15
}
}
Problem
The above code works OK in most cases, except when COLLECTION is a temporary object.
More specifically, dangling pointer potentially occurs when I create adapter of adapter of adapter ....
int func1(int i){ return i+10; }
int func2(int i){ return i+100; }
template<class T> auto utilityAdapter(const T& t){
auto adapter1=CollectAdapterWidget::createAdapter(t,func1);
auto adapter12=CollectAdapterWidget::createAdapter(adapter1,func2);
//"adapter12.collection_" point to "adapter1"
return adapter12;
//end of scope, "adapter1" is deleted
//"adapter12.collection_" will be dangling pointer
}
int main(){
std::vector<int> test;
test.push_back(5);
for(auto b:utilityAdapter(test)){
std::cout<< b<<std::endl; //should 5+10+100 = 115
}
}
This will cause run time error. Here is the dangling-pointer demo.
In the real usage, if the interface is more awesome, e.g. use | operator, the bug will be even harder to be detected :-
//inside "utilityAdapter(t)"
return t|func1; //OK!
return t|func1|func2; //dangling pointer
Question
How to improve my library to fix this error while keeping performance & robustness & maintainablilty near the same level?
In other words, how to cache data or pointer of COLLECTION (that can be adapter or real data-structure) elegantly?
Alternatively, if it is easier to answer by coding from scratch (than modifying my code), go for it. :)
My workarounds
The current code caches by pointer.
The main idea of workarounds is to cache by value instead.
Workaround 1 (always "by value")
Let adapter cache the value of COLLECTION.
Here is the main change:-
COLLECTION collection_; //<------ #1
//changed from .... COLLECTION* collection_;
Disadvantage:-
Whole data-structure (e.g. std::vector) will be value-copied - waste resource.
(when use for std::vector directly)
Workaround 2 (two versions of library, best?)
I will create 2 versions of the library - AdapterValue and AdapterPointer.
I have to create related classes (Widget,AdapterIterator,etc.) as well.
AdapterValue - by value. (designed for utilityAdapter())
AdapterPointer - by pointer. (designed for std::vector)
Disadvantage:-
Duplicate code a lot = low maintainability
Users (coders) have to be very conscious about which one to pick = low robustness
Workaround 3 (detect type)
I may use template specialization that do this :-
If( COLLECTION is an "CollectAdapter" ){ by value }
Else{ by pointer }
Disadvantage:-
Not cooperate well between many adapter classes.
They have to recognize each other : recognized = should cache by value.
Sorry for very long post.
I personally would go with template specialisation – however, not specialise the original template, but a nested class instead:
template<typename Collection, typename Adapter>
class CollectAdapter
{
template<typename C>
class ObjectKeeper // find some better name yourself...
{
C* object;
public:
C* operator*() { return object; };
C* operator->() { return object; };
};
template<typename C, typename A>
class ObjectKeeper <CollectAdapter<C, A>>
{
CollectAdapter<C, A> object;
public:
CollectAdapter<C, A>* operator*() { return &object; };
CollectAdapter<C, A>* operator->() { return &object; };
};
ObjectKeeper<Collection> keeper;
// now use *keeper or keeper-> wherever needed
};
The outer class then covers both cases by just always using pointers while the nested class hides the differences away.
Sure, incomplete (you yet need to add appropriate constructors, for instance, both to outer and inner class), but it should give you the idea...
You might even allow the user to select if she/he wants to copy:
template<typename Collection, typename Adapter, bool IsAlwaysCopy = false>
class CollectAdapter
{
template<typename C, bool IsCopy>
class ObjectWrapper // find some better name yourself...
{
C* object;
public:
C* operator*() { return object; };
C* operator->() { return object; };
};
template<typename C>
class ObjectWrapper<C, true>
{
C object;
public:
C* operator*() { return &object; };
C* operator->() { return &object; };
};
// avoiding code duplication...
template<typename C, bool IsCopy>
class ObjectKeeper : public ObjectWrapper<C, IsCopy>
{ };
template<typename C, typename A, bool IsCopy>
class ObjectKeeper <CollectAdapter<C, A>, IsCopy>
: public ObjectWrapper<CollectAdapter<C, A>, true>
{ };
ObjectKeeper<Collection> keeper;
};
In my indexed_view I store the value of the collection if it is an rvalue, and store a reference if it is an lvalue. You could do the same here: overload your operator| for both rvalues and lvalues.
template<typename Collection,typename Filter>
auto operator|(Collection&& collection,Filter filter){
return create_adapter_for_rvalue_collection(collection,filter);
}
template<typename Collection,typename Filter>
auto operator|(Collection const& collection,Filter filter){
return create_adapter_for_const_lvalue_collection(collection,filter);
}
template<typename Collection,typename Filter>
auto operator|(Collection & collection,Filter filter){
return create_adapter_for_non_const_lvalue_collection(collection,filter);
}

factory, unique_ptr and static_cast

Consider polymorphic classes with a base object, a derived interface, and a final object:
// base object
struct object
{
virtual ~object() = default;
};
// interfaces derived from base object
struct interface1 : object
{
virtual void print_hello() const = 0;
template<typename T>
static void on_destruction(object* /*ptr*/)
{
std::cout << "interface1::on_destruction" << std::endl;
}
};
// final object
struct derived1 : interface1
{
virtual void print_hello() const override
{
std::cout << "hello" << std::endl;
}
static std::string get_type_name()
{
return "derived1";
}
};
In the real use case, final objects are defined through a plugin system, but that is not the point. Note that I want to be able to call on_destruction when an object is destroyed (see register_object below). I want to use these classes as follows:
int main()
{
// register derived1 as an instantiable object,
// may be called in a plugin
register_object<derived1>();
// create an instance using the factory system
auto instance = create_unique<interface1>("derived1");
instance->print_hello();
return 0;
}
Using std::unique_ptr to manage the objects, I ended up with the following code for register_object:
template<typename T>
using unique = std::unique_ptr<
T,
std::function<void(object*)> // object deleter
>;
namespace
{
std::map< std::string, std::function<unique<object>(void)> > factory_map;
}
template<typename T>
void register_object()
{
factory_map.emplace(
T::get_type_name(),
[]()
{
unique<T> instance{
new T,
[](object* ptr)
{
T::on_destruction<T>(ptr);
delete ptr;
}
};
return static_move_cast<object>(
std::move(instance)
);
}
);
}
And the create* functions:
unique<object> create_unique_object(const std::string& type_name)
{
auto f = factory_map.at(type_name);
return f();
}
template<typename T>
unique<T> create_unique(const std::string& type_name)
{
return static_move_cast<T>(
create_unique_object(type_name)
);
}
You noticed in register_object and create_unique the call to static_move_cast, which is declared as:
template<typename U, typename T, typename D>
std::unique_ptr<U, D>
static_move_cast
(
std::unique_ptr<T, D>&& to_move_cast
)
{
auto deleter = to_move_cast.get_deleter();
return std::unique_ptr<U, D>{
static_cast<U*>(
to_move_cast.release()
),
deleter
};
}
The goal behind static_move_cast is to allow static_cast on std::unique_ptr while moving the deleter during the cast. The code is working, but I feel like hacking std::unique_ptr. Is there a way to refactor the code to avoid my static_move_cast?
static_move_cast is unnecessary within register_object, since you can just use the converting constructor of unique_ptr template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ):
unique<T> instance{
new T,
// ...
};
return instance;
Or, even simpler, construct and return a unique<object> directly, since T* is convertible to object*:
return unique<object>{
new T,
// ...
};
However for create_unique the use of static_move_cast is unavoidable, since the converting constructor of unique_ptr won't work for downcasts.
Note that shared_ptr has static_pointer_cast, which performs downcasts, but there is no corresponding facility for unique_ptr, presumably because it it is considered straightforward and correct to perform the cast yourself.
I would say it is good solution given the requirements. You transfer the responsibility to the caller of create_unique. He must give correct combination of type and string and string that is in the registry.
auto instance = create_unique<interface1>("derived1");
// ^^^^^^^^^^ ^^^^^^^^
// what if those two don't match?
You could improve it a bit by changing the static_cast to dynamic_cast. And the caller of create_unique should always check that he got non-null pointer before calling anything on it.
Or at least use dynamic_cast with assert in debug mode, so you catch mismatches while developing.
Alternative refactoring: Have separate factory for every existing interface.

How can I create a factory function template that constructs object given an arbitrary number of arguments?

This is easier to explain with some code so I'll give an example first:
#include <iostream>
#include <vector>
class Base {
public:
int integer;
Base() : integer(0) {}
Base(int i) : integer(i) {}
};
class Double: public Base {
public:
Double(int i) { integer = i * 2; }
};
class Triple: public Base {
public:
Triple(int i) { integer = i * 3; }
};
template<typename T>
Base* createBaseObject(int i) {
return new T(i);
};
int main() {
std::vector<Base*> objects;
objects.push_back(createBaseObject<Double>(2));
objects.push_back(createBaseObject<Triple>(2));
for(int i = 0; i < objects.size(); ++i) {
std::cout << objects[i]->integer << std::endl;
}
std::cin.get();
return 0;
}
I am trying to make a function that will return a Base pointer to an object that is derived from Base. In the above code the function createBaseObject allows me to do that but it restricts me in that it can only create dervied classes that take a single argument into their constructor.
For example if I wanted to make a derived class Multiply:
class Multiply: public Base {
public:
Multiply(int i, int amount) { integer = i * amount; }
};
createBaseObject wouldn't be able to create a Multiply object as it's constructor takes two arguments.
I want to ultimately do something like this:
struct BaseCreator {
typedef Base* (*funcPtr)(int);
BaseCreator(std::string name, funcPtr f) : identifier(name), func(f) {}
std::string identifier;
funcPtr func;
};
then, for example, when I get input matching identifier I can create a new object of whatever derived class associates with that identifier with whatever arguments were input too and push it to the container.
After reading some of the replies I think something like this would suit my needs to be able to procedurally create an instance of an object? I'm not too wise with templates though so I do not know whether this is legal.
struct CreatorBase {
std::string identifier;
CreatorBase(std::string name) : identifier(name) {}
template<typename... Args>
virtual Base* createObject(Args... as) = 0;
};
template<typename T>
struct Creator: public CreatorBase {
typedef T type;
template<typename... Args>
Base* createObject(Args... as) {
return new type(as...);
}
};
Okay here's another semi-solution I've managed to come up with so far:
#include <boost\lambda\bind.hpp>
#include <boost\lambda\construct.hpp>
#include <boost\function.hpp>
using namespace boost::lambda;
boost::function<Base(int)> dbl = bind(constructor<Double>(), _1);
boost::function<Base(int, int)> mult = bind(constructor<Multiply>(), _1, _2);
Just this has the same limits as the original in that I can't have a single pointer that will point to both dbl and mult.
C++11 variadic templates can do this for you.
You already have your new derived class:
class Multiply: public Base {
public:
Multiply(int i, int amount) { integer = i * amount; }
};
Then change your factory:
template<typename T, typename... Args>
Base* createBaseObject(Args... as) {
return new T(as...);
};
And, finally, allow the arguments to be deduced:
objects.push_back(createBaseObject<Multiply>(3,4));
Live demo.
As others have said, though, it does all seem a little pointless. Presumably your true use case is less contrived.
Why not provide multiple overloads with templated parameters?
template<typename TBase, TArg>
Base* createBaseObject(TArg p1) {
return new TBase(p1);
};
template<typename TBase, TArg1, TArg2>
Base* createBaseObject(TArg p1, TArg2 p2) {
return new TBase(p1, p2);
};
Use variadic templates:
template <typename R, typename ...Args>
Base * createInstance(Args &&... args)
{
return new R(std::forward<Args>(args)...);
}
Usage: objects.push_back(createInstance<Gizmo>(1, true, 'a'));
It's a bit hard to see why you would want this, though, as you might as well just say:
objects.push_back(new Gizmo(1, true, 'a'));
Even better would be to declare the vector to carry std::unique_ptr<Base> elements.