How can I pass a lambda (c++11) into a templated function? - c++

I'm playing around with lambda functions in gcc 4.6.2, and would like to implement a templated "map" function like this:
template<typename A, typename B> std::vector<B> map(const std::vector<A>& orig, const std::function<B(A)> f) {
std::vector<B> rv;
rv.resize(orig.size());
std::transform(begin(orig), end(orig), begin(rv), f);
return rv;
}
This doesn't work, because the test code:
int main(int argc, char **argv) {
std::vector<int> list;
list.push_back(10);
list.push_back(20);
list.push_back(50);
std::vector<int> transformed = map(list, [](int x) -> int { return x + 1; });
std::for_each(begin(transformed), end(transformed), [](int x) { printf("-> %d\n", x); });
return 0;
}
gives this error:
test.cpp:49:80: error: no matching function for call to ‘map(std::vector<int>&, main(int, char**)::<lambda(int)>)’
test.cpp:49:80: note: candidate is:
test.cpp:6:49: note: template<class A, class B> std::vector<B> map(const std::vector<A>&, std::function<B(A)>)
If I remove the templating, and use a vector directly, it compiles fine:
std::vector<int> map(const std::vector<int>& orig, const std::function<int(int)> f) {
std::vector<int> rv;
rv.resize(orig.size());
std::transform(begin(orig), end(orig), begin(rv), f);
return rv;
}
so it must be a problem with the way I'm defining the template.
Has anyone run into this before? I know lambdas are incredibly new.

You don't need to use std::function. Just make the predicate parameter a template value. For example,
template<typename A, typename B> std::vector<B> map(const std::vector<A>& orig, B f) {
std::function<> is more useful as a member value type or for defining non-templated code.

The problem is that the compiler can't figure out what to use for B. In order to determine that type it wants to use the function<> you pass in for f, but you don't pass an std::function<> directly. You pass in something you expect to be used to construct a function<>. And in order to do that implicit construction it needs to know the type of argument. So you've got this circular dependency where the type of argument depends on what you pass in, but what gets passed in depends on the type of argument.
You can break this circular dependency by specifying the template parameters, such as map_<int,int>(list, [](int x) -> char { return x + 1; });
(although I see the functor actually returns a char, not an int, so if the type deduction worked for you here you'd be getting back a vector<char> which cannot be converted to a vector<int> when you assign the result to transformed)
However as has been pointed out, generally templates take functors as just a plain template type:
template<typename A,typename Func>
auto map_(const std::vector<A>& orig, Func f) -> std::vector<decltype(f(A()))> {
std::vector<decltype(f(A()))> rv;
/*...*/
}
(we use the trailing return type because we need to use the expression f in the return type, which isn't available unless the return type comes afterwards.)
This allows the template to deduce the functor type directly and avoids any type conversions and best allows for optimization.
It's also customary to use iterators as arguments on these sorts of functions, in which case your function is just a wrapper around std::transform, so you can just use that directly. I'm not sure there's a whole lot of value in a special version that deals with vectors specifically.

I'm tackling with lambdas too and i noticed that you can declare a function pointer in a function definition's parameter list and when you make a call to that function you can pass a lambda expression as an argument if it matches the function prototype of course.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
template <typename T,typename C>
struct map {
typedef C (*F)(const T&);
std::vector<C> rv;
map () {}
map (const std::vector<T>& o,F f) {
rv.resize(o.size());
std::transform (o.begin(),o.end(),rv.begin(),f);
}
~map () {}
operator std::vector<C> () const {
return rv;
}
};
int main () {
std::vector<int> asd(5,12);
std::vector<char> transformed=map<int,char>(asd,[](const int& x)->char {return x+1;});
std::copy (transformed.begin(),transformed.end(),std::ostream_iterator<int>(std::cout," "));
}

Related

How to properly store lambda functions in a tuple and call them?

I'm trying to create a class that can store functions in a member tuple. But when trying to put lambdas inside of an object's tuple (through function pointers) I'm getting a error. Please explain, what I'm doing wrong and what is the proper way of releasing this idea. I think there should be an elegant and stylistically correct general solution (in terms of functional programming patterns) to avoid boilerplate code in class description, objects creation and filling them with functions.
#include <functional>
#include <string>
#include <iostream>
template<typename... ArgTypes>
class MyClass {
public:
//boolean function of some argument
template<typename Type> using Func = bool(Type const &);
//type for a tuple of pointers to templated boolean functions
template<typename... Types> using TupleOfFunctions = typename std::tuple<Func<Types>*...>;
//the tuple
TupleOfFunctions<ArgTypes...> _tuple;
//constructor
MyClass(TupleOfFunctions<ArgTypes...> t) : _tuple(t) {
}
};
int main(int argc, char** argv) {
MyClass<int, std::string> M({
[](int &arg) { return arg > 0; },
[](std::string &arg) { return arg == "abc"; }
});
std::cout << (*std::get<0>(M._tuple))(1);
std::cout << (*std::get<1>(M._tuple))("xyz");
return 0;
}
The error I get is
./test.cpp:26:3: error: no matching function for call to 'MyClass<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::MyClass(<brace-enclosed initializer list>)'
26 | });
template<typename Type> using Func = bool(Type const &);
This line suggested functions taking in const type arguments. However:
[](int &arg) { return arg > 0; },
[](std::string &arg) { return arg == "abc"; }
These two lines suggested non-const arguments.
Either remove the const from the first line, or add const to the second two should solve it.
Could you, however, suggest some ideas of redesigning the class so that the boilerplate code of repeated explicit declaration of these types (in class template specification and lambda function arguments) can be avoided?
Part of the point of having lambda is anonymous function type. Actually trying to deduce a type of them, like what you did, was kind of going backward.
One way I would suggest to do this would be:
template<typename ... Lambdas>
class MyClass {
public:
std::tuple<Lambdas...> _tuple;
MyClass(Lambdas ... args) : _tuple(std::make_tuple(args ...)) {
}
};
Now you can use it like:
MyClass M(
[](const int &arg) { return arg > 0; },
[](const std::string &arg) { return arg == "abc"; }
);
Alternatively, you might be interested in a variant/visit pattern: https://godbolt.org/z/5Pdn1Ynqe
A braced-init-list, like {}, does not actually have a type. In the context of template deduction, you can only use them in certain cases - when deducing against initializer_list (where T is a function template parameter) or when the corresponding parameter is already deduced by something else. In this case, neither of those two things is true - so the compiler cannot figure out what ...ArgTypes is supposed to be.
I think you should use std::make_tuple and store as lambda as function pointer.
Live example

What's the least verbose way to hint a overloaded function template as template parameter

I'm trying to create a function template which accepts std::max and others with compatible prototypes:
template <typename F>
int f(F g)
{
return g(1,2);
}
Because of the many overloads, the template argument F cannot be inferred f.e. for std::max, so this will fail:
f(std::max);
One possibility is to hint with a static_cast:
f(static_cast<int const& (*)(int const&,int const&)>(std::max));
I'm looking for a less verbose way while still being able to also easily pass any other sort of matching function, like f.e.
f([](int i, int j) { return 3; });
f(std::function<int(int,int)>([](int i, int j) { return 4; }));
Here's a godbolt.
If there's an easy way for C++11 and C++14 this would be great but if there's only one for C++17 and above this would also help a lot.
The issue is std::max not your function.
There is no way you could modify your function to make it accept a set of overloads. A set of overloads is just not something you can pass along. What you can pass along is an object with overloaded operator(). For example
struct foo {
template <typename T> bool operator()(T a,T b){return a+b;}
};
f(foo{}); // OK
std::max however is a function template and you need to instantiate the function before the function can be passed to f. Nothing you can do about that. Though you not necessarily need std::function or static_cast to pick the right overload. As mentioned in a comment you can do
f([](int a, int b) { return std::max(a, b); });
This triggers instantiation of std::max<int> inside the lambda, or if you prefer to select the type inside f you can do similar as in the above example:
f([](auto a, auto b) { return std::max(a,b); });
This lambda expression is similar to the above foo. You have a concrete object and only the operator() is a template which only gets instantiated when called, such that in f you could even do:
template <typename F>
int f(F g)
{
if (some_condition) return g(1,2); // calls std::max<int>
else return g(1.2,1.4); // calls std::max<double>
// (though int is returned anyhow)
}
f([](auto a, auto b) { return std::max(a,b); });

Can a std::function typedef be used to help define a lambda?

Let's say a I have a typedef for a specific std::function such as:
typedef std::function<int(int a, int b, int c)> func_type;
Can I reuse that typedef when defining a lambda that implements it?
For example, in the example below, the function foo accepts a func_type, but the call-site for foo needs to replicate the signature:
void foo(func_type f) {
// ...
}
int main() {
foo([](int a, int b, int c){ return a + b + c; });
}
Can I somehow re-use the func_type typedef when declaring the lambda, so I don't have to repeat the argument list (and so changes to the func_type typedef will be transparent for lambda bodies that work with the new definition).
Something like [](??? func_type ???){ return a + b + c; }.
The variable names in std::function<int(int a, int b, int c)> are not part of the type -- they are basically comments. There is no way to extract them at any other point.
So if you hope to get a, b and c you are out of luck.
One simple thing you can do is use auto:
foo( [](auto...args) { return args+...+0; } );
which is close to what you want. If you have 3 arguments you can do:
foo( [](auto a, auto b, auto c) { return a+b+c; } );
But the return type doesn't match, other than because std::function does the conversion for you.
You can extract the types of a b and c and make the lambda work differently, but not with the return type. Not unless you do something insane like:
template<class T>
struct tag_t{ contexpr tag_t(){} using type=T; };
template<class T>
constexprt tag_t<T> tag{};
template<class Tag>
using type_t = typename Tag::type;
template<class F>
struct deducer {
F f;
template<class R, class...Args>
operator std::function<R(Args...)>() const {
return f( tag<R>, tag<Args>... );
}
};
template<class F>
deducer<F> make_deducer( F f ){ return {std::move(f)}; }
int main() {
foo(make_deducer([](auto R, auto...Args){
return []( type_t<decltype(Args)>... args )->type_t<decltype(R)> {
return 0+...args;
});
}));
}
I would advise against this. But I deduced the argument types and return type of the lambda from what std::function I was passed to.
What we do here is we create a deducer type, that when converted to a std::function passes the arguments and return type expected to a lambda it stores. That lambda then generates a custom lambda for those exact arguments.
This is neither brief, simple nor sane.
If you know you have a std::function and what you want to do is defer the selection of the type arguments to std::function, you can just have a generic lambda:
foo([](auto... xs) { return (... + xs); });
Since it's std::function's call operator that drives how the lambda is called, this'll do the right thing. Of course, this requires C++14 (and the fold-expression I used above requires C++17, but that's not as important). You may or may not want to use auto&&, depending on what the types actually are.
For C++11, you can't easily do such a thing with a lambda. You'd need to fix the arity and manually list all the types. This isn't practical. You could fallback to using a normal function object, with a call operator template, but then you lose the advantages of a lambda.
A std::function is
is a general-purpose polymorphic function wrapper. Instances of
std::function can store, copy, and invoke any Callable target --
functions, lambda expressions, bind expressions, or other function
objects, as well as pointers to member functions and pointers to data
members. -- source cppreference.com
So yes, this approach is perfectly valid !
However the signature of the typedef can't be taken over to short-circuit the lambda definition.
Remark: The typedef is about the return type and the parameter types but not the parameter names, so if short-circuiting the parameter list would be legal, the body of the lambda would not know which parameters to use:
int main() {
foo([](int d, int e, int f){ return d + e + f; });
}

Parameter to use std::greater or std::less as argument

I would like to make a function with a parameter that accepts either std::greater<int> or std::less<int> as the argument. I'm stuck on the syntax for the parameter, though.
This is the format I tried:
myFunction(int a, int b, bool *comp(int, int)) { … }
…
std::greater<int> bigger;
myFunction(2, 3, bigger);
That doesn't work, though, and I suspect the third parameter is just completely wrong. What should it actually be?
cannot convert std::greater<int> to bool* (*)(int, int)
Functions taking a comparator are usually implemented via templates:
template <typename Comparator>
myFunction(int a, int b, Comparator comp) { … }
but you could also use std::function to implement it:
myFunction(int a, int b, std::function<bool (int, int)> ) { … }
The first version exposes code in the header but will usually perform better.
As for the second version, you can hide the implementation in the .cpp file,
but you would lose some performance due to the impossibility to inline the
comparator calls.
So the trick here is that std::less and std::greater are actually stateless function objects that can be trivially constructed. But they don't support casting to a function pointer.
The efficient choices are either (A) take the comparator via template argument and implement the code in a header:
template<typename C> void myFunc( int a, int b, C comp )
which means you have to implement it in a header file, or (B) type erase the function object via a std::function< bool(int, int) >:
void myFunc( int a, int b, std::function< bool(int, int) > comp )
which has some costs (maybe significant? Profile!) (heap allocation is avoided via small object optimization for stateless std less/greater, but it tends to cost a virtual function call regardless, which can also block inlining).
Or (C) write some code that lets you take a stateless functor and turn it into a function pointer:
template<typename T>
using Type = T;
template<typename StatelessFunctor>
struct function_ptr_of_stateless_t {
template<typename R, typename... Args>
operator Type<R(Args...)>*() const {
return [](Args... args)->R {
return StatelessFunctor()(std::forward<Args>(args)...);
};
}
};
template<typename StatelessFunctor>
function_ptr_of_stateless_t<StatelessFunctor> as_function_ptr() {
return {};
}
bool myFunction( int a, int b, bool(*comp)(int, int) ) { return comp(a,b); }
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<int>>() ) << "\n";
}
where the template function as_function_ptr takes the type of your stateless functor and creates a throw away type that lets you cast it to any compatible function pointer type.
This has modestly less overhead than the std::function solution, as a call over a function pointer tends to be faster than over a virtual method, and in addition some compilers (like gcc) are quite decent at inlining function pointers, even from one compilation unit to another.
As a bonus, in C++14 you could use:
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<>>() ) << "\n";
}
and it still works pretty optimally.
Use a template:
template<class Callable>
myFunction(int a, int b, Callable f);

functor generation from member function pointer type

I am trying to simplify (via make_fn()) the generation of functors that preprocess parameters (via wrap()) for member functions of arity n.
Generating the functors is basically working, but until now only by explicitly specifying the parameter types for the member function.
Now i'd like to generate the correct functor from the member function type it handles:
struct X {};
template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
bool wrap(C* c, X x)
{
return (c->*F)(process<T1>(x));
}
template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(F f) // <- problem here, F is not a type
{
return boost::bind(&wrap<C, T1, F>, _1, _2);
}
With this however, vc++ and g++ don't see F as a type for the parameter of make_fn(). I must miss something obvious here and am feeling somewhat blind.
The idea was that it should work like this:
struct A
{
bool f1(bool) { return true; }
};
void test()
{
A a;
X x;
make_fn(&A::f1)(&a, x);
}
Any ideas on how to make that work?
Background:
I have a fixed interface which, when simplified, looks like this:
bool invoke(C* c, const char* const functionName, int argCount, X* args);
X is a variant type which i have to convert to certain backend types (int, std::string, ...).
To handle these calls i have a map of functors that are looked up by name and map these calls to member functions of some instance.
The intention of the wrapping is to avoid manual conversions and instead generate functors which do the conversion for me or throw. I have this working with a macro based solution, but that solution requires to specify the types and the parameter count explicitly.
Via function overload resolution i hope to generate the correct converting functor implicitly from the member function signature.
It appears to me that you are attempting to turn a pointer passed to a function into a non-type template argument, which I'm afraid is not going to work (see comments to your question).
What you could do, is to store the function pointer in a function object. The following appears to compile:
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct X {};
template <class T>
bool process(X) { return true; }
template <class C, class T1, class Func>
struct wrap1
{
typedef bool result_type;
Func f;
wrap1(Func f): f(f) {}
bool operator()(C* c, X x)
{
return (c->*f)(process<T1>(x));
}
};
template<class C, typename T1>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(bool (C::*f)(T1))
{
return boost::bind(wrap1<C, T1, bool (C::*)(T1)>(f), _1, _2);
}
struct A
{
bool f1(bool) { return true; }
};
void test()
{
A a;
X x;
make_fn(&A::f1)(&a, x);
}
However, I'm not sure if that is any good and how you would create the rest of the wrappers. For the latter you might just get a compiler that supports variadic templates. :)