I want to create lambda that will accept any number of arguments like:
template <typename... Args>
void f(Args... args) {
auto l = [args...]() {
g(args...);
}
// use l
}
Problem here is that it doesn't work with move-only types. If it was only 1 arg I would do smth like
void f(Arg arg) {
auto l = [arg = std::move(arg)]() {
g(move(arg));
}
}
How to move all args to lambda?
template <class... Args>
void f(Args... args) {
auto l = [tup=std::make_tuple(std::move(args)...)] {
std::apply([](auto&&...args){
g(decltype(args)(args)...);
}, tup );
};
}
A bit icky.
Pack them into a tuple, then unpack tuple with std::apply. If you lack std::apply write yourself an equivalent one.
If you want to invoke g with rvalues, make outer lambda mutable, and move tuple into inner lambda.
Inner lambda can capture by default & if you want access to args of outer or the like.
We can even abstract this pattern a bit:
template<class F, class...Args>
auto forward_capture( F&& f, Args&&...args ) {
return [
f=std::forward<F>(f),
tup=std::make_tuple(std::forward<Args>(args)...)
]{
return std::apply( f, tup );
};
}
use:
template <typename... Args>
void f(Args... args) {
auto l = forward_capture(
[](auto&&...args) {
g(args...);
},
std::move(args)...
);
// use l
}
If you want the capture list first, we can do it:
template<class...Args>
auto forward_capture( Args&&...args ) {
return [
tup=std::make_tuple(std::forward<Args>(args)...)
](auto&& f)mutable{
return [
f=decltype(f)(f),
tup=std::move(tup)
]{
return std::apply( f, tup );
};
};
}
use:
template <typename... Args>
void f(Args... args) {
auto l = forward_capture(std::move(args)...)(
[](auto&&...args) {
g(args...);
}
);
// use l
}
which has the "advantage" that we have 3 nested lambdas.
Or more fun:
template<class...Args>
struct arrow_star {
std::tuple<Args...> args;
template<class F>
auto operator->*(F&& f)&& {
return [f=std::forward<F>(f),args=std::move(args)]()mutable{
return std::experimental::apply( std::move(f), std::move(args) );
};
}
};
template<class...Args>
arrow_star<std::decay_t<Args>...> forward_capture( Args&&...args ) {
return {std::make_tuple(std::forward<Args>(args)...)};
}
template<class...Args>
auto f(Args... args)
{
return
forward_capture( std::move(args)... )
->*
[](auto&&...args){
g(decltype(args)(args)...);
};
}
live example.
Related
Consider the following (https://godbolt.org/z/sfT3aesvK):
#include <utility>
#include <vector>
struct A { constexpr static int type = 0; };
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A>(std::forward<Args>(args)...);
};
std::vector<int(*)(Args&&...) /* what goes here? */> vec{{call_with_A}};
int acc = 0;
for (auto fn : vec) {
acc += fn(std::forward<Args>(args)...);
}
return acc;
}
int bar() {
return 1 + foo([]<typename T>(int a, int b) {
return T::type + a + b;
}, 2, 3);
}
The above does not compile, because
no known conversion from '(lambda at <source>:8:24)' to 'int (*)(int &&, int &&)' for 1st argument
My question is what the template type T so that std::vector<T> will accept call_with_A as an element?
I tried to print what decltype(call_with_A) is, but this seems to just be a (lambda at [...]) expression for the compiler.
The type of a lambda expression is "unutterable". It cannot be written down directly. However, you can declare a typedef alias for the type:
auto call_with_A = /* lambda */;
using LambdaType = decltype(call_with_A);
std::vector<LambdaType> vec = {call_with_A};
You can also use class template argument deduction if you don't need to mention the type anyway:
auto call_with_A = /* lambda */;
std::vector vec = {call_with_A};
// the type of `vec` is `std::vector<decltype(call_with_A)>`
Every lambda has a different type - even they have the same signature. Lambda functions that have identical body also have different type.
You can declare a vector of type using decltype. However, it is not useful. For example.
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A1 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A2 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
std::vector<decltype(call_with_A)> vec;
vec.push_back(call_with_A);
vec.push_back(call_with_A1); // Not OK
vec.push_back(call_with_A2); // Not OK
return 0;
}
Your best option is to use std::vector of std::function. For example.
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A1 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A2 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
std::vector<std::function<int(Args...)>> vec;
vec.push_back(call_with_A);
vec.push_back(call_with_A1);
vec.push_back(call_with_A2);
return 0;
}
related post: How to combine std::bind(), variadic templates, and perfect forwarding?
Is there a way to bind a function with variadic tuples ? Here incorrect code indicating the intent:
// t is an instance of T
auto f = std::bind(&T::iterate,t,???);
// args is an instance of std::tuple<Args...> args;
std::apply(f,args);
(note: I am unsure "variadic tuple" to be the right terminology. Looking forward editing the post with your correction)
Since C++20 you can use std::bind_front:
template<class T>
void print (T val) {
std::cout << val << std::endl;
}
struct T {
template<class ... Args>
void iterate(Args... args) {
int temp[] = { (print(args),0)... };
}
};
// all happens here
template<class ... Args>
void foo(const tuple<Args...>& args) {
T t;
auto f = std::bind_front(&T::iterate<Args...>,&t);
std::apply(f,args);
}
// the call
int i = 1;
foo(std::make_tuple(i,i+1,"bind is cool"));
If you want to use old std::bind, you can provide your own placeholders to be generated from pack:
template<int N>
struct MyPlaceholder {};
namespace std {
template<int N>
struct is_placeholder<MyPlaceholder<N>> : public integral_constant<int, N> {};
}
template<class ... Args, size_t ... Indices>
void foo2helper(const tuple<Args...>& args, std::index_sequence<Indices...>) {
T t;
auto f = std::bind(&T::iterate<Args...>,&t, (MyPlaceholder<Indices+1>{})...);
std::apply(f,args);
}
template<class ... Args>
void foo2(const tuple<Args...>& args) {
foo2helper(args, std::make_index_sequence<sizeof...(Args)>{});
}
// the call
foo2(std::make_tuple(2.34,"only bind"));
Live demo
Don't use bind, use a lambda instead:
auto f = [&t](auto... args){ t.iterate(args...); };
std::apply(f, args);
If you want perfect forwarding, that would look like:
auto f = [&t](auto&&... args){ t.iterate(std::forward<decltype(args)>(args)...); };
std::apply(f, args);
I have the following piece of code (c++11):
template <typename F,
typename FirstT,
typename... FIn>
auto min_on(F f, FirstT first, FIn... v) -> typename std::common_type<FirstT, FIn...>::type
{
using rettype = typename std::common_type<FirstT, FIn...>::type;
using f_rettype = decltype(f(first));
rettype result = first;
f_rettype result_trans = f(first);
f_rettype v_trans;
(void)std::initializer_list<int>{
((v_trans = f(v), v_trans < result_trans)
? (result = static_cast<rettype>(v), result_trans = v_trans, 0)
: 0)...};
return result;
}
Which basically returns the argument result that produced the minimum value for expression f(result). This can be called like this:
auto mod7 = [](int x)
{
return x % 7;
};
auto minimum = min_on(mod7, 2, 8, 17, 5);
assert( minimum == 8); // since 8%7 = 1 -> minimum value for all arguments passed
Now I would like to use this in a 'curried' way so that I can get a variadic lambda from min_on and then call it with arguments (that I might receive later), like so:
auto mod7 = [](int x)
{
return x % 7;
};
auto f_min = min_on(mod7);
auto minimum = f_min(2, 8, 17, 5);
// or
auto minimum = min_on(mod7)(2, 8, 17, 5);
Is this even possible?
In C++11, the following works if you’re willing to manually create the function object:
template <typename F>
struct min_on_t {
min_on_t(F f) : f(f) {}
template <typename T, typename... Ts>
auto operator ()(T x, Ts... xs) -> typename std::common_type<T, Ts...>::type
{
// Magic happens here.
return f(x);
}
private: F f;
};
template <typename F>
auto min_on(F f) -> min_on_t<F>
{
return min_on_t<F>{f};
}
And then call it:
auto minimum = min_on(mod7)(2, 8, 17, 5);
To use lambdas in C++14, you need to omit the trailing return type because you cannot specify the type of the lambda without assigning it to a variable first, because a lambda expression cannot occur in an unevaluated context.
template <typename F>
auto min_on(F f)
{
return [f](auto x, auto... xs) {
using rettype = std::common_type_t<decltype(x), decltype(xs)...>;
using f_rettype = decltype(f(x));
rettype result = x;
f_rettype result_trans = f(x);
(void)std::initializer_list<int>{
(f(xs) < result_trans
? (result = static_cast<rettype>(xs), result_trans = f(xs), 0)
: 0)...};
return result;
};
}
Not sure on C++11, but in C++14, you could create a lambda to wrap your function in:
auto min_on_t = [](auto f) {
return [=](auto ... params) {
return min_on(f, params...);
};
};
auto min_t = min_on_t(mod7);
auto minimum = min_t(2, 8, 17, 5);
Live on Coliru
In C++14 this is easy.
template<class F>
auto min_on( F&& f ) {
return [f=std::forward<F>(f)](auto&& arg0, auto&&...args) {
// call your function here, using decltype(args)(args) to perfect forward
};
}
Many compilers got auto return type deduction and arguments in lambdas working prior to full C++14 support. So a nominal C++11 compiler might be able to compile this:
auto min_on = [](auto&& f) {
return [f=decltype(f)(f)](auto&& arg0, auto&&...args) {
// call your function here, using decltype(args)(args) to perfect forward
};
}
in C++11:
struct min_on_helper {
template<class...Args>
auto operator()(Args&&...args)
-> decltype( min_on_impl(std::declval<Args>()...) )
{
return min_on_impl(std::forward<Args>(args)...);
}
};
is boilerplate. This lets us pass the entire overload set of min_on_impl around as one object.
template<class F, class T>
struct bind_1st_t {
F f;
T t;
template<class...Args>
typename std::result_of<F&(T&, Args...)>::type operator()(Args&&...args)&{
return f( t, std::forward<Args>(args)... );
}
template<class...Args>
typename std::result_of<F const&(T const&, Args...)>::type operator()(Args&&...args)const&{
return f( t, std::forward<Args>(args)... );
}
template<class...Args>
typename std::result_of<F(T, Args...)>::type operator()(Args&&...args)&&{
return std::move(f)( std::move(t), std::forward<Args>(args)... );
}
};
template<class F, class T>
bind_1st_t< typename std::decay<F>::type, typename std::decay<T>::type >
bind_1st( F&& f, T&& t ) {
return {std::forward<F>(f), std::forward<T>(t)};
}
gives us bind_1st.
template<class T>
auto min_on( T&& t )
-> decltype( bind_1st( min_on_helper{}, std::declval<T>() ) )
{
return bind_1st(min_on_helper{}, std::forward<T>(t));
}
is modular and solves your problem: both min_on_helper and bind_1st can be tested independently.
You can also replace bind_1st with a call to std::bind, but in my experience the quirks of std::bind make me extremely cautious about recommending that to anyone.
So I wrote a function that composes "sequentially" void lambdas so that I can use them at once in an algorithm:
template <typename F, typename... Fs>
auto lambdaList(F f, Fs... fs)
{
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
}
template <typename F>
auto lambdaList(F f)
{
return [=] (auto&... args) { f(args...); };
}
It works if I use local lambdas, but not when I use functions in a different namespace:
#include <iostream>
namespace foo {
void a() { std::cout << "a\n"; }
void b() { std::cout << "b\n"; }
}
template <typename F, typename... Fs>
auto lambdaList(F f, Fs... fs)
{
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
}
template <typename F>
auto lambdaList(F f)
{
return [=] (auto&... args) { f(args...); };
}
int main() {
auto printStarBefore = [] (const std::string& str) {
std::cout << "* " + str;
};
auto printStarAfter = [] (const std::string& str) {
std::cout << str + " *" << std::endl;
};
lambdaList(printStarBefore, printStarAfter)("hi"); // ok
lambdaList(foo::a, foo::b)(); // error
}
The error is no matching function for call to 'lambdaList()' with:
main.cpp:11:56: note: candidate expects at least 1 argument, 0 provided
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
~~~~~~~~~~^~~~~~~
Why does it sometimes work but sometimes not?
You need to invert your functions:
template <typename F>
auto lambdaList(F f)
{
return [=] (auto&... args) { f(args...); };
}
template <typename F, typename... Fs>
auto lambdaList(F f, Fs... fs)
{
return [=] (auto&... args) { f(args...); lambdaList(fs...)(args...); };
}
As-is, your base case won't be found by unqualified lookup in your recursive case - it can only be found by argument dependent lookup. If the arguments aren't in the same namespace as lambdaList, then it won't be found at all and the recursive step will always call itself. That's the source of your error.
The new ordering allows the base-case lambdaList() to be found by normal unqualified lookup - now it's visible at the point of definition of the recursive lambdaList().
That said, we can do better. Write one function that invokes everything:
template <typename... Fs>
auto lambdaList(Fs... fs) {
using swallow = int [];
return [=](auto const&... args) {
(void)swallow{0,
(void(fs(args...)), 0)...
};
};
}
And now we don't need to worry about any kind of lookup. If you have access to a modern-enough compiler that supports some C++1z features, the above can be greatly reduced with:
template <typename... Fs>
auto lambdaList(Fs... fs) {
return [=](auto const&... args) {
(fs(args...), ...);
};
}
That's downright understandable!
My problem is the following:
I have a class declared as such:
template<typename ReturnType, typename... Args>
class API
{
ReturnType operator()(Args... args)
{
// Get argument 0
// Get argument 1
}
};
I am in need of getting the arguments on by one, and so far the only way I've come up to (but I can not get it to work) is using std::get, as such:
std::get<0>(args);
Of course, this leads to a lot of errors.
I am new to variadic templates (and to C++11 at all) so I am quite lost at this point.
How could I get those arguments one by one?
Any help will be appreciated.
Capture the args in a temporary tuple (Live at Coliru):
ReturnType operator()(Args... args)
{
static_assert(sizeof...(args) >= 3, "Uh-oh, too few args.");
// Capture args in a tuple
auto&& t = std::forward_as_tuple(args...);
// Get argument 0
std::cout << std::get<0>(t) << '\n';
// Get argument 1
std::cout << std::get<1>(t) << '\n';
// Get argument 2
std::cout << std::get<2>(t) << '\n';
}
std::forward_as_tuple uses perfect forwarding to capture references to the args, so there should be no copying.
You can use recursion.
Here's an example:
#include <iostream>
template<typename ReturnType>
class API {
public:
template<typename Arg>
ReturnType operator()(Arg&& arg) {
// do something with arg
return (ReturnType) arg;
}
template<typename Head, typename... Tail>
ReturnType operator()(Head&& head, Tail&&... tail) {
// do something with return values
auto temp = operator()(std::forward<Head>(head));
return temp + operator()(std::forward<Tail>(tail)...);
}
};
int main() {
API<int> api;
auto foo = api(1, 2l, 2.0f);
std::cout << foo;
return 0;
}
A few helper templates can do that for you. I'm not aware of one in stl that does it directly, but I like to roll my own templates anyways:
namespace Internal {
template <size_t Pos, typename Arg, typename... Args>
struct Unpacker {
static auto unpack(Arg&&, Args&&... args) {
return Unpacker<Pos - 1, Args...>::unpack(std::forward<Args>(args)...);
}
};
template <typename Arg, typename... Args>
struct Unpacker<0, Arg, Args...> {
static auto unpack(Arg&& arg, Args&&...) { return std::forward<Arg>(arg); }
};
} // Internal
template <size_t Pos, typename... Args>
auto unpack(Args&&... args) {
return Internal::Unpacker<Pos, Args...>::unpack(std::forward<Args>(args)...);
}
Then you can use it like this:
auto unpacked0 = unpack<0>(1, "orange", 3.3f, "pie");
auto unpacked1 = unpack<1>(1, "orange", 3.3f, "pie");
auto unpacked2 = unpack<2>(1, "orange", 3.3f, "pie");
auto unpacked3 = unpack<3>(1, "orange", 3.3f, "pie");
// Will not compile, because there are only 4 arguments
// auto unpacked4 = unpack<4>(1, "orange", 3.3f, "pie");
fmt::print("{} {} {} {}\n", unpacked0, unpacked1, unpacked2, unpacked3);
Or in your case:
template<typename ReturnType, typename... Args>
class API {
ReturnType operator()(Args&&... args) {
// Get argument 0
auto& arg0 = unpack<0>(args...);
// Get argument 1
auto& arg1 = unpack<1>(args...);
}
};