Convert void* to std::function<void()> - c++

Is store function pointers with different parameters in a vector of void pointers.
unordered_map<string, vector<void*> > List;
template <typename T>
void Listen(string Name, function<void(T)> Function)
{
List[Name].push_back(&Function);
}
Then I want to call them, assuming that T is the same type for Fire as used for the Listen.
template <typename T>
void Fire(string Name, T Data)
{
auto Functions = List[Name];
for (auto i = Functions.begin(); i != Functions.end(); ++i)
{
(function<void(T)>)i)(Data);
}
}
But I get a compiler error which reads error C2064: term does not evaluate to a function taking 1 arguments in file ...\vc\include\xrefwrap 431 1.
What am I doing wrong?

For one, you're taking the address of a parameter, here:
List[Name].push_back(&Function);
Then you're trying to convert an iterator object to a std::function object here:
(function<void(T)>)i)
What you trying to do can be done, like this, although it's not pretty, to put it mildly:
unordered_map<string, vector<void*> > List;
template <typename T>
void Listen(string Name, function<void(T)> &Function)
{
List[Name].push_back(&Function);
}
template <typename T>
void Fire(string Name, T Data)
{
auto Functions = List[Name];
for (auto i = Functions.begin(); i != Functions.end(); ++i)
{
function<void(T)> *ptr = *i;
(*ptr) (Data);
}
}
It can break in lot of ways, for example you have no control that the function, registered under some name in Listen is called with the correct argument in Fire - consider calling Listen<int> ("foo", f); and then doing Fire<double> ("foo", 3.14);
Another approach - just pass closures for callbacks:
unordered_map<string, std::vector<function<void()> > > List;
void Listen(string Name, function<void()> Function)
{
List[Name].push_back(Function);
}
void Fire(string Name)
{
auto Functions = List[Name];
for (auto i = Functions.begin(); i != Functions.end(); ++i)
(*i) ();
}

#include <functional>
#include <unordered_map>
#include <memory>
#include <string>
#include <vector>
template<typename T> struct BlockDeduction{typedef T type;};
struct BaseCallback {
virtual ~BaseCallback();
template<typename T>
void DoCall( typename BlockDeduction<T>::type&& t ) const;
};
template<typename T>
struct Callback: BaseCallback
{
std::function<void(T)> func;
Callback( std::function<void(T)> const& f ):func(f) {}
};
template<typename T>
void BaseCallback::DoCall( typename BlockDeduction<T>::type&& t ) const {
Assert( dynamic_cast<Callback<T>const*>(this) );
static_cast<Callback<T>const*>(this).func(std::forward(t));
}
typedef std::unique_ptr<BaseCallback> upCallback;
template<typename T>
upCallback make_callback( std::function<void(T)> const& f ) {
return upCallback( new Callback<T>( f ) );
}
struct Listener {
std::unordered_map< std::string, std::vector<upCallback>> List;
template<typename T>
void Listen( std::string Name, std::function<void(T)> f) {
List[Name].push_back( make_callback(f) );
}
template<typename T>
void Fire( std::string Name, typename BlockDeduction<T>::type&& t ) {
auto callbacks = List.find(Name);
if (callbacks == List.end()) return;
for(auto it = callbacks->second.begin(); it != callbacks->second.end(); ++it) {
if (it +1 = callbacks->second.end())
{
(**it).DoCall<T>( std::forward(t) );
} else {
(**it).DoCall<T>( t );
}
}
}
};
... or something like that.
This stores a copy of the std::function in the map, wrapped up generically. Memory is handled via a unique_ptr. I carefully blocked type deduction at points where the type must be exactly what you used when you installed the Listener (automatic type deduction at that point is rather fragile).
In debug, you'll get an assertion failure if you violate the Name<->type mapping.
Some extra work needs to be done for nullary callbacks. Just write a DoCall that casts BaseCallback to Callback<void>, specialize Callback<void> to be a nullary function wrapper, specialize make_callback on nullary function, and write a Fire(string) method for Listener that calls the bare DoCall.
Or create a struct Empty and use lambdas to wrap nullary functions in function<void(Empty)>, which would involve slightly less code, but would be slower at run-time.

Related

Call a variadic template functor in a variadic template parameter pack if it satisfies a condition

I have a variadic template functor class:
template <typename Result, typename... Arguments>
class Functor
{
public:
using FunctionType = std::function<Result(Arguments...)>;
Result operator() (const Arguments&... arguments) { return Function(arguments); }
std::string GetName() { return Name; }
Functor(const std::string& name, const FunctionType& function) : Name(name), Function(function) { }
private:
std::string Name;
FunctionType Function;
}
and a variadic template function:
template <typename... Functors>
void Function(const Functors&... functors) { }
Let's say I have declared some Functors and want to use them in Function:
Functor<int, int> f
(
"f",
[](int x) -> int { return 2 * x - 1; }
);
Functor<int, int, int> g
(
"g",
[](int x, int y) -> int { return x + 2 * y - 3; }
);
Function(f, g);
Inside Function, I want to find out which Functor passed to it in the parameter pack satisfies a certain condition, and if it does, call the functor. Like the following pseudocode:
template <typename... Functors>
void Function(const Functors&... functors)
{
foreach (Functor functor in functors)
{
if (functor.GetName() == "f")
{
functor(); // the functor can have different parameter lists so this is another problem
}
}
}
I want to know if there's a way to do this. I also want to know that since the Functors can have varying parameter lists, how do I call them even if I were able to find the correct Functor to call? Suppose that there's a std::vector<int> and when the Functor takes three ints as its argument, is it possible to take the first three ints and pass them to the Functor?
In C++17, this is easily solvable using fold expressions.
#include <functional>
#include <string>
template <typename Result, typename... Arguments>
class Functor
{
public:
using FunctionType = std::function<Result(Arguments...)>;
Result operator() (const Arguments&... args) {
return this->Function(arguments...);
}
std::string GetName() {
return this->Name;
}
Functor(const std::string& name, const FunctionType& function)
: Name(name), Function(function) { }
private:
std::string Name;
FunctionType Function;
};
template <typename... Functors>
void ForEachFunctor(const Functors&... functors)
{
((functors.getName() == "f" && functors()), ...);
}
Here, we exploit the short-circuiting of the && operator. Only if the condition functors.getName() == "f" is true, will the right hand side of the operator be evaluated.
A slightly less hacky approach uses a separate function:
template <typename Functor>
void InvokeIfNamedF(const Functor &functor) {
if (functor.GetName() == "f")
functor();
}
template <typename... Functors>
void ForEachFunctor(const Functors&... functors)
{
(InvokeIfNamedF(functors), ...);
}
The elements of the parameter pack are combined using the comma-operator. However, in this example, we are invoking each functor with no parameters. If all functors have distinct signatures then passing them as one pack and invoking them conditionally all at once is probably not possible.

Deduce lambda expression in a template function call C++ [duplicate]

I'm trying to catch up on C++11 and all the great new features. I'm a bit stuck on lambdas.
Here's the code I was able to get to work:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <functional>
using namespace std;
template<typename BaseT, typename Func>
vector<BaseT> findMatches(vector<BaseT> search, Func func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
What I would like to have is this:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Basically I want to narrow down the possible lambdas to a sensible subset of functions.
What am I missing? Is this even possible? I'm using GCC/G++ 4.6.
Stephan T. Lavavej explains why this doesn't work in this video. Basically, the problem is that the compiler tries to deduce BaseT from both the std::vector and the std::function parameter. A lambda in C++ is not of type std::function, it's an unnamed, unique non-union type that is convertible to a function pointer if it doesn't have a capture list (empty []). On the other hand, a std::function object can be created from any possible type of callable entity (function pointers, member function pointers, function objects).
Note that I personally don't understand why you would want to limit the incoming functors to that specific signature (in addition to the fact that indirection through a polymorphic function wrapper, like std::function, is by far more inefficient than a direct call to a functor (which may even be inlined)), but here's a working version. Basically, it disables argument deduction on the std::function part, and only deduces BaseT from the std::vector argument:
template<class T>
struct Identity{
typedef T type;
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Live example on Ideone.
Another possible way would be to not restrict the functor type directly, but indirectly through SFINAE:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype(bool(fun(v[0])), void())
{
// ...
}
Live example on Ideone.
This function will be removed from the overload set if fun doesn't take an argument of type T& or if the return type is not convertible to bool. The , void() makes f's return type void.
As has been revealed by other posters, this is a template argument deduction for std::function.
One intuitive way to make the second code snippet work is to add your base type when calling the template function: findMatches<int>.
Another way not mentioned by Xeo is using std::is_convertible:
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
It avoids wrapping lamda into std::function, and provides a cleaner error message.

how to get rid of lambda syntax

I need to make those function in the "normal" syntax. how do i change it?
template <template <class, class> class Container>
typename const Container<Course*, std::allocator<Course*> > Schedule<Container>::getAllCourses( ) const
{
Container<Course*, std::allocator<Course*> > newone;
std::for_each(courses.begin(), courses.end(), [&newone](Course *c)
{Course* nc = new Course(c->getName(),c->getNumber(), c->getFaculty()); newone.push_back(nc);});
//make a container and push into it every course
return newone;
}
actually, I need to change the function "for_each" that it will use outside class.
I don't know how to do it. can you help?
A lambda function is a closure type, implemented as an unnamed functor.
You could look into those keywords, to understand how to perform a "conversion". Pretty much the rule would be that this lambda :
[capture_clause](args) -> return_type { /* lambda_body */ }
is practically (in a simplified view - generic lambdas or value/ref captures not explicitly shown here) this
struct no_name
{
no_name(capture_clause) : /* Initialize the closure */ { }
return_type operator()(args) { /* lambda_body */ }
};
In your case, you'd have to a make a class like the following :
template <template <class, class> class Container>
struct lamda_fun
{
Container<Course*, std::allocator<Course*> > &newone;
lamda_fun(Container<Course*, std::allocator<Course*> > &newone)
: newone(newone) {
}
void operator()(Course *c) {
Course* nc = new Course(c->getName(),c->getNumber(), c->getFaculty());
newone.push_back(nc);
}
};
If you still want to get rid of the lambda syntax call it like
std::for_each(courses.begin(), courses.end(), lamda_fun<Container>(newone));
Even though a copy of the functor will be passed to for_each, the functor wraps a reference so the correct thing will be done.
An easier way would be to just use a for loop though (yes those still exist)
// range based version
for (auto c : courses) {
Course* nc = new Course(c->getName(), c->getNumber(), c->getFaculty());
newone.push_back(nc);
}
// traditional version
for (auto it = courses.begin(), ite = courses.end(); it != ite; ++it)
{
auto c = *it;
Course* nc = new Course(c->getName(), c->getNumber(), c->getFaculty());
newone.push_back(nc);
}
You might replace the lambda with a local class:
#include <algorithm>
#include <iostream>
#include <vector>
template <class Container>
Container transform(const Container& container) {
struct Lambda {
Container& result;
Lambda(Container& result) : result(result) {}
void operator () (const typename Container::value_type& value) {
result.push_back(value + 1);
}
};
Container result;
std::for_each(container.begin(), container.end(), Lambda(result));
return result;
}
int main() {
std::vector<int> u;
u.push_back(0);
u.push_back(1);
u.push_back(2);
std::vector<int> v = transform(u);
std::cout << v[0] << v[1] << v[2] << '\n';
}

Inserting a variadic argument list into a vector?

Forgive me if this has been answered already, as I couldn't find it...
Basically I have an object that needs to take a variadic argument list in it's constructor and store the arguments in a vector. How do I initialize a vector from a the arguments of a variadic constructor?
class GenericNode {
public:
GenericNode(GenericNode*... inputs) {
/* Something like... */
// inputs_.push_back(inputs)...;
}
private:
std::vector<GenericNode*> inputs_;
};
The best thing would be to use an initializer list
#include <initializer_list>
#include <vector>
class GenericNode {
public:
GenericNode(std::initializer_list<GenericNode*> inputs)
:inputs_(inputs) {} //well that's easy
private:
std::vector<GenericNode*> inputs_;
};
int main() {
GenericNode* ptr;
GenericNode node{ptr, ptr, ptr, ptr};
} //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c
The closest to what you already have, using C++11 is to use the vector's initializer_list:
template<class ...Ts>
GenericNode(Ts... inputs)
:inputs_{inputs...} {} //well that's easy too
//compilation at http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae
And here's a C++11 version with no initializer_lists at all. It's ugly, and complicated, and requires features missing from many compilers. Use the initializer list
template<class T>
using Alias = T;
class GenericNode {
public:
template<class ...Ts>
GenericNode(Ts... inputs) { //SFINAE might be appropriate
using ptr = GenericNode*;
Alias<char[]>{( //first part of magic unpacker
inputs_.push_back(ptr(inputs))
,'0')...,'0'}; //second part of magic unpacker
}
private:
std::vector<GenericNode*> inputs_;
};
int main() {
GenericNode* ptr;
GenericNode node(ptr, ptr, ptr, ptr);
} //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
//thanks to R. Martinho Fernandes for helping me get it to compile
Unrelated to everything, I don't know if those are owning pointers or not. If they are, use std::unique_ptr instead.
// inputs_.push_back(inputs)...;
This doesn't work because you can't expand a parameter pack as a statement, only in certain contexts such as a function argument list or initializer-list.
Also your constructor signature is wrong, if you're trying to write a variadic template it needs to be a template!
Once you write your constructor signature correctly the answer is easy, just construct the vector with the pack expansion:
#include <vector>
class GenericNode
{
public:
template<typename... T>
GenericNode(T*... inputs) : inputs_{ inputs... }
{ }
private:
std::vector<GenericNode*> inputs_;
};
(You could instead have set it in the constructor body with:
inputs_ = { inputs... };
but the cool kids use member initializers not assignment in the constructor body.)
The downside of this solution is that the template constructor accepts any type of pointer arguments, but will then give an error when trying to construct the vector if the arguments aren't convertible to GenericNode*. You could constrain the template to only accept GenericNode pointers, but that's what happens automatically if you do what the other answers suggest and make the constructor take a std::initializer_list<GenericNode*>, and then you don't need any ugly enable_if SFINAE tricks.
You can't use a variadic argument list unless it's a template, you can, as stated, use a initializer_list like this:
class GenericNode {
public:
GenericNode(std::initializer_list<GenericNode*> inputs) : inputs_(inputs)
{
}
private:
std::vector<GenericNode*> inputs_;
};
template <class ... T>
GenericNode* foo(T ... t)
{
return new GenericNode({t...});
}
class Blob
{
std::vector<std::string> _v;
public:
template<typename... Args>
Blob(Args&&... args)
: _v(std::forward<Args>(args)...)
{ }
};
int main(void)
{
const char * shapes[3] = { "Circle", "Triangle", "Square" };
Blob b1(5, "C++ Truths");
Blob b2(shapes, shapes+3);
}
Example from C++11 Truths looks simple enough...;)
Not a complete solution but might give you some ideas.
Another way to do it:
#include <iostream>
#include <vector>
using std::vector;
template <typename T>
void variadic_vector_emplace(vector<T>&) {}
template <typename T, typename First, typename... Args>
void variadic_vector_emplace(vector<T>& v, First&& first, Args&&... args)
{
v.emplace_back(std::forward<First>(first));
variadic_vector_emplace(v, std::forward<Args>(args)...);
}
struct my_struct
{
template <typename... Args>
my_struct(Args&&... args)
{
variadic_vector_emplace(_data, std::forward<Args>(args)...);
}
vector<int>& data() { return _data; }
private:
vector<int> _data;
};
int main()
{
my_struct my(5, 6, 7, 8);
for(int i : my.data())
std::cout << i << std::endl;
}
I recently wrote the following function that takes a string with
{1} , {2} , {3} ... in it and substitutes the argument list. I ran in to the same problem until I decided to let the compiler work it out for itself with the auto keyword.
#include <string>
#include <vector>
using std::string;
using std::vector;
template<typename S, typename... Args>
string interpolate( const S& orig , const Args&... args)
{
string out(orig);
auto va = {args...};
vector<string> v{va};
size_t i = 1;
for( string s: v)
{
string is = std::to_string(i);
string t = "{" + is + "}";
try
{
auto pos = out.find(t);
if(pos != out.npos)
{
out.erase(pos, t.length());
out.insert( pos, s);
}
i++;
}
catch( std::exception& e)
{
std::cerr << e.what() << std::endl;
}
} // for
return out;
}
Apparently that is good enough as long as the types line up correctly.
In this case I am using only std::string throughout.
I think this is an elegant technique, but it may have drawbacks.
Note: If the element-type of a vector is not copy-initializable (it is in OP post), the std::initializer list route will not work.
You can still use a variadic unpack statement (post C++ 17):
(inputs_.emplace_back(std::move(args)), ...);

Lambdas and std::function

I'm trying to catch up on C++11 and all the great new features. I'm a bit stuck on lambdas.
Here's the code I was able to get to work:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <functional>
using namespace std;
template<typename BaseT, typename Func>
vector<BaseT> findMatches(vector<BaseT> search, Func func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
What I would like to have is this:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Basically I want to narrow down the possible lambdas to a sensible subset of functions.
What am I missing? Is this even possible? I'm using GCC/G++ 4.6.
Stephan T. Lavavej explains why this doesn't work in this video. Basically, the problem is that the compiler tries to deduce BaseT from both the std::vector and the std::function parameter. A lambda in C++ is not of type std::function, it's an unnamed, unique non-union type that is convertible to a function pointer if it doesn't have a capture list (empty []). On the other hand, a std::function object can be created from any possible type of callable entity (function pointers, member function pointers, function objects).
Note that I personally don't understand why you would want to limit the incoming functors to that specific signature (in addition to the fact that indirection through a polymorphic function wrapper, like std::function, is by far more inefficient than a direct call to a functor (which may even be inlined)), but here's a working version. Basically, it disables argument deduction on the std::function part, and only deduces BaseT from the std::vector argument:
template<class T>
struct Identity{
typedef T type;
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Live example on Ideone.
Another possible way would be to not restrict the functor type directly, but indirectly through SFINAE:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype(bool(fun(v[0])), void())
{
// ...
}
Live example on Ideone.
This function will be removed from the overload set if fun doesn't take an argument of type T& or if the return type is not convertible to bool. The , void() makes f's return type void.
As has been revealed by other posters, this is a template argument deduction for std::function.
One intuitive way to make the second code snippet work is to add your base type when calling the template function: findMatches<int>.
Another way not mentioned by Xeo is using std::is_convertible:
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
It avoids wrapping lamda into std::function, and provides a cleaner error message.