Simulating std::forward with std::forward_as_tuple - c++

Let's say I use std::forward_as_tuple to store the arguments of a function call in a tuple
auto args = std::forward_as_tuple(std::forward<Args>(args)...);
And then I pass this tuple by lvalue reference to a function that wants to invoke a function foo() with some of the arguments in args as determined by another std::integer_sequence. I do it with std::move() like so
template <typename TupleArgs, std::size_t... Indices>
decltype(auto) forward_to_foo(TupleArgs&& args,
std::index_sequence<Indices...>) {
return foo(std::get<Indices>(std::move(args))...);
}
And this would work because the rvalue qualified version of std::get<std::tuple> return std::tuple_element_t<Index, tuple<Types...>>&& which is an identity transformation of the reference-ness of the std::tuple_element_t<Index, tuple<Types...>> because of reference collapsing with the &&.
So if std::tuple_element_t<Index, tuple<Types...>> evaluates to T& the returned type would be T& && which is just T&. Similar reason for when std::tuple_element_t<Index, tuple<Types...>> returns T&& and T
Am I missing something? Are there some cases where this would fail?

template <typename TupleArgs, std::size_t... Indices>
decltype(auto) forward_to_foo(TupleArgs&& args,
std::index_sequence<Indices...>) {
return foo(std::get<Indices>(std::forward<TupleArgs>(args))...);
}
This is the correct implementation.
Use should look like:
auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
forward_to_foo( std::move(tuple_args), std::make_index_sequence<sizeof...(args)>{} );
there are a few differences here.
First, we take by forwarding reference, not by lvalue reference. This lets the caller provide rvalue (prvalue or xvalue) tuples to us.
Second, we forward the tuple into the std::get call. This means we only pass get an rvalue reference if the tuple was moved into us.
Third, we move into forward_to_foo. This ensures the above does the right thing.
Now, imagine if we wanted to call foo twice.
auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
auto indexes = std::make_index_sequence<sizeof...(args)>{};
forward_to_foo( tuple_args, indexes );
forward_to_foo( std::move(tuple_args), indexes );
we don't have to touch forward_to_foo at all, and we never move from any of the args more than once.
With your original implementation, any calls to forward_to_foo silently move from TupleArgs rvalue references or values without any indication at the call-site that we are destructive on the first parameter.
Other than that detail, yes that emulates forwarding.
Myself I'd just write a notstd::apply:
namespace notstd {
namespace details {
template <class F, class TupleArgs, std::size_t... Indices>
decltype(auto) apply(F&& f, TupleArgs&& args,
std::index_sequence<Indices...>) {
return std::forward<F>(f)(std::get<Indices>(std::forward<TupleArgs>(args))...);
}
}
template <class F, class TupleArgs>
decltype(auto) apply(F&& f, TupleArgs&& args) {
constexpr auto count = std::tuple_size< std::decay_t<TupleArgs> >{};
return details::apply(
std::forward<F>(f),
std::forward<TupleArgs>(args),
std::make_index_sequence< count >{}
);
}
}
then we do:
auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
auto call_foo = [](auto&&...args)->decltype(auto){ return foo(decltype(args)(args)...); };
return notstd::apply( call_foo, std::move(tuple_args) );
which moves the tricky bit into notstd::apply, which attempts to match the semantics of std::apply, which lets you replace it down the road with a more standard bit of code.

Related

C++: Unpack a tuple with references and values without copying/moving too much

Let's say I have a tuple t whose type is std::tuple<T1,T2,T3> where each T may be either Obj, Obj&, Obj&&,const Obj&. I want to write a function which unpacks the values of the tuple into a function f which accepts three types that decay to Obj. I want to avoid useless copying as much as possible, how I do it?
My current implementation is
static R call(C2&& c, TUP&& x) {
using TUP0 = typename std::remove_reference<TUP>::type;
return c(std::forward<typename std::tuple_element<0, TUP0>::type>(std::get<0>(x)),
std::forward<typename std::tuple_element<1, TUP0>::type>(std::get<1>(x)),
std::forward<typename std::tuple_element<2, TUP0>::type>(std::get<2>(x)));
}
But this implementation seems to move things when TUP is std::tuple<Obj,Obj,Obj>, even though it should only move when TUP contains an Obj&&.
In C++17, this is known as std::apply():
static R call(C2&& c, TUP&& x) {
return std::apply(std::forward<C2>(c), std::forward<TUP>(x));
}
This can be implemented in C++11 by using the index sequence trick. std::make_index_sequence only got added to the standard library in C++14, but it itself is also implementable in C++11 and I will not include that implementation here:
namespace detail {
template <class F, class Tuple, size_t... Is>
auto apply_impl(F&& f, Tuple&& t, index_sequence<Is...>)
-> decltype(std::forward<F>(f)(std::get<Is>(std::forward<Tuple>(t))...))
{
return std::forward<F>(f)(std::get<Is>(std::forward<Tuple>(t))...);
}
}
template <class F, class Tuple>
auto apply(F&& f, Tuple&& t)
-> decltype(details::apply_impl(std::forward<F>(f), std::forward<Tuple>(t), make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{}))
{
return details::apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{});
}
There seems to be some confusion with what std::get() actually does. Note that it depends on the reference qualification of the tuple. Here are the relevant overloads:
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&
get( tuple<Types...>& t );
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get( tuple<Types...>&& t );
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >const&
get( const tuple<Types...>& t );
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >const&&
get( const tuple<Types...>&& t );
The returning type matches the const and ref qualifications of the input tuple. That is given a std::tuple<int> a, std::tuple<int&> b, and std::tuple<int&&> c:
std::get<0>(a); // int&
std::get<0>(std::move(a)); // int&&
std::get<0>(b); // int&
std::get<0>(std::move(b)); // int&, because reference collapsing
std::get<0>(c); // int&, because reference collapsing
std::get<0>(std::move(c)); // int&&
std::get<I>(std::forward<TUP>(x)) gives you the correct, safe type of reference, regardless of the type of the that member of the tuple. std::get<0>(c) gives you an lvalue reference - which is correct behavior. If you want an rvalue reference out, you need an rvalue in. Per usual.
If I get the question right, the desired behaviour is: Pass on an rvalue reference only if the element type is "rvalue reference" or if the element type is "value in an rvalue tuple" while otherwise passing on lvalue references.
1. In case of an lvalue T = std::tuple<Obj, Obj&, Obj&&>& object tuple:
Don't move first element (Obj) 1
Don't move second element (Obj&)
Move third element (Obj&&) 2
1: std::forward<std::tuple_element_t<I, T>>(std::get<I>(tuple)...) won't do that job as the result will be Obj&&. Also std::get<I>(std::move(tuple))... won't either give the desired behaviour as the result will again be Obj&&.
2: Here std::get<I>(std::forward<T>(tuple))... won't give the desired value type as the result will be Obj&.
2. In case of an rvalue T = std::tuple<Obj, Obj&, Obj&&>&& object tuple:
Move first element (Obj)
Don't move second element (Obj&)
Move third element (Obj&&)
std::get<I>(std::forward<T>(tuple))... will do the trick on rvalues.
Thus what I think you want is:
tuple<Obj>& -> Obj&
tuple<Obj&>& -> Obj&
tuple<Obj&&>& -> Obj&&
tuple<Obj>&& -> Obj&&
tuple<Obj&>&& -> Obj&
tuple<Obj&&>&& -> Obj&&
While the answer of #Oktalist will give you the desired behaviour, there's another way to do it:
namespace detail
{
template<std::size_t I, class ... Ts>
decltype(auto) get(std::tuple<Ts...>& x)
{
using T = std::tuple_element_t<I, std::tuple<Ts...>>;
return static_cast<std::conditional_t<
std::is_reference<T>::value, T, T&>>(std::get<I>(x));
}
template<std::size_t I, class ... Ts>
decltype(auto) get(std::tuple<Ts...>&& x)
{
return std::get<I>(std::move(x));
}
}
template<class C2, class TUP>
decltype(auto) call(C2&& c, TUP&& x) {
return std::forward<C2>(c)(
detail::get<0>(std::forward<TUP>(x)),
detail::get<1>(std::forward<TUP>(x)),
detail::get<2>(std::forward<TUP>(x)));
}
The problem is that std::forward will cast a non-reference type to an rvalue reference. You want a function that will cast a non-reference type to an lvalue reference but preserve the reference category if the type is already a reference:
template <typename T>
constexpr decltype(auto) stable_forward(std::remove_reference_t<T>& arg) {
return static_cast<std::conditional_t<std::is_reference<T>::value, T, T&>>(arg);
}
template <typename T>
constexpr decltype(auto) stable_forward(std::remove_reference_t<T>&& arg) {
return static_cast<std::conditional_t<std::is_reference<T>::value, T, T&&>>(arg);
}
static R call(C2&& c, TUP&& x) {
using TUP0 = std::remove_reference_t<TUP>;
return c(stable_forward<std::tuple_element_t<0, TUP0>>(std::get<0>(std::forward<TUP>(x))),
stable_forward<std::tuple_element_t<1, TUP0>>(std::get<1>(std::forward<TUP>(x))),
stable_forward<std::tuple_element_t<2, TUP0>>(std::get<2>(std::forward<TUP>(x))));
}
Apologies for C++14, the transformation to C++11 is left as an exercise to the reader.
I've answered the question as asked. How wise it is I cannot say. Barry's answer might serve you better if you can adjust your code to supply the tuple as an rvalue.

c++ : Multiple move on the same object and perfect forwarding

In this question I talked about how to create a multi-function memoizator. In one of the answers, it was suggested to implement perfect forwarding, so passing the arguments to desired function will result inexpensive, like this:
template <typename ReturnType, typename... Args>
ReturnType callFunction(MemFunc<ReturnType, Args...> memFunc, Args&& ... args) //rvalue reference of args
{
auto it = multiCache.find(memFunc.name);
if (it == multiCache.end())
throw KeyNotFound(memFunc.name);
boost::any anyCachedFunc = it->second;
function < ReturnType(Args...)> cachedFunc = boost::any_cast<function<ReturnType(Args...)>> (anyCachedFunc);
return cachedFunc(forward<Args> (args) ...);//perfect forwarding
}
I'm not an expert of move semantic and perfect forwarding, but from what I've understood we need to pass an rvalue when we call callFunction.
So the first callFunction calling is illegal, while the second one is:
typedef vector<double> vecD;
MultiMemoizator mem;
//lambda function that returns the sorted vector (just for fun)
function<vecD(vecD)> sort_vec = [](vecD vec) {
sort(vec.begin(),vec.end());
return vec;
};
vector<vecD> vec;
// here fill vec...
mem.callFunction<double, double>(sortFunc, vec); //error! vec is an lvalue
mem.callFunction<double, double>(sortFunc, move(vec));//OK: move(vec) return an rvalue of the lvalue (vec)
The problem is that in this application, callFunction is supposed to be called several times on the same object, which is not supposed to happen once we call move on our object.
So for example:
mem.callFunction<double, double>(sortFunc, move(vec));//First time: sorting will take A LONG time because vec is not memoized
//now is not safe to use vec anymore...but it's memoized for sortFunc
mem.callFunction<double, double>(sortFunc, move(vec));//computed quickly because of memoization, but unsafe because of first move!
So from what I can understand I have to make a choice:
Give up on perfect forwarding implementing callFunction(MemFunc<ReturnType, Args...> memFunc, Args ... args) (or Args & ... args) , but introducing an expensive copy when we call cachedFunc(args)
Keep the efficient perfect forwarding, but introduce possible unexpected behaviour on multiple move on the same object
Obviously the second choice is not acceptable, so how can I avoid the first one?
A POSSIBLE SOLUTION:
The solution posted above is too much restrictive for the user: what if he wants, for some reason, to use vec again? So a possible solution could be to overload callFunction so it accept both solutions:
//rvalue reference/move/perfect forwarding implementation
template <typename ReturnType, typename... Args>
ReturnType callFunction(MemFunc<ReturnType, Args...> memFunc, Args&& ... args) {
...
return cachedFunc(forward<Args> (args) ...);//perfect forwarding
}
//lvalue reference/no perfect forwarding implementation
template <typename ReturnType, typename... Args>
ReturnType callFunction(MemFunc<ReturnType, Args...> memFunc, Args& ... args) {
...
return cachedFunc(args);//expensive!
}
This solution has some disadvantage or could lead to some problem?

How to iterate over a std::tuple in C++ 11 [duplicate]

This question already has answers here:
How can you iterate over the elements of an std::tuple?
(23 answers)
Closed 8 years ago.
I have made the following tuple:
I want to know how should I iterate over it? There is tupl_size(), but reading the documentation, I didn't get how to utilize it. Also I have search SO, but questions seem to be around Boost::tuple .
auto some = make_tuple("I am good", 255, 2.1);
template<class F, class...Ts, std::size_t...Is>
void for_each_in_tuple(const std::tuple<Ts...> & tuple, F func, std::index_sequence<Is...>){
using expander = int[];
(void)expander { 0, ((void)func(std::get<Is>(tuple)), 0)... };
}
template<class F, class...Ts>
void for_each_in_tuple(const std::tuple<Ts...> & tuple, F func){
for_each_in_tuple(tuple, func, std::make_index_sequence<sizeof...(Ts)>());
}
Usage:
auto some = std::make_tuple("I am good", 255, 2.1);
for_each_in_tuple(some, [](const auto &x) { std::cout << x << std::endl; });
Demo.
std::index_sequence and family are C++14 features, but they can be easily implemented in C++11 (there are many available on SO). Polymorphic lambdas are also C++14, but can be replaced with a custom-written functor.
Here is an attempt to break down iterating over a tuple into component parts.
First, a function that represents doing a sequence of operations in order. Note that many compilers find this hard to understand, despite it being legal C++11 as far as I can tell:
template<class... Fs>
void do_in_order( Fs&&... fs ) {
int unused[] = { 0, ( (void)std::forward<Fs>(fs)(), 0 )... }
(void)unused; // blocks warnings
}
Next, a function that takes a std::tuple, and extracts the indexes required to access each element. By doing so, we can perfect forward later on.
As a side benefit, my code supports std::pair and std::array iteration:
template<class T>
constexpr std::make_index_sequence<std::tuple_size<T>::value>
get_indexes( T const& )
{ return {}; }
The meat and potatoes:
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
do_in_order( [&]{ f( get<Is>(std::forward<Tuple>(tup)) ); }... );
}
and the public-facing interface:
template<class Tuple, class F>
void for_each( Tuple&& tup, F&& f ) {
auto indexes = get_indexes(tup);
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f) );
}
while it states Tuple it works on std::arrays and std::pairs. It also forward the r/l value category of said object down to the function object it invokes. Also note that if you have a free function get<N> on your custom type, and you override get_indexes, the above for_each will work on your custom type.
As noted, do_in_order while neat isn't supported by many compilers, as they don't like the lambda with unexpanded parameter packs being expanded into parameter packs.
We can inline do_in_order in that case
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
int unused[] = { 0, ( (void)f(get<Is>(std::forward<Tuple>(tup)), 0 )... }
(void)unused; // blocks warnings
}
this doesn't cost much verbosity, but I personally find it less clear. The shadow magic of how do_in_order works is obscured by doing it inline in my opinion.
index_sequence (and supporting templates) is a C++14 feature that can be written in C++11. Finding such an implementation on stack overflow is easy. A current top google hit is a decent O(lg(n)) depth implementation, which if I read the comments correctly may be the basis for at least one iteration of the actual gcc make_integer_sequence (the comments also point out some further compile-time improvements surrounding eliminating sizeof... calls).
Alternatively we can write:
template<class F, class...Args>
void for_each_arg(F&&f,Args&&...args){
using discard=int[];
(void)discard{0,((void)(
f(std::forward<Args>(args))
),0)...};
}
And then:
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
for_each_arg(
std::forward<F>(f),
get<Is>(std::forward<Tuple>(tup))...
);
}
Which avoids the manual expand yet compiles on more compilers. We pass the Is via the auto&&i parameter.
In C++1z we can also use std::apply with a for_each_arg function object to do away with the index fiddling.
Here is a similar and more verbose solution than the formerly accepted one given by T.C., which is maybe a little bit easier to understand (-- it's probably the same as thousand others out there in the net):
template<typename TupleType, typename FunctionType>
void for_each(TupleType&&, FunctionType
, std::integral_constant<size_t, std::tuple_size<typename std::remove_reference<TupleType>::type >::value>) {}
template<std::size_t I, typename TupleType, typename FunctionType
, typename = typename std::enable_if<I!=std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type >
void for_each(TupleType&& t, FunctionType f, std::integral_constant<size_t, I>)
{
f(std::get<I>(std::forward<TupleType>(t)));
for_each(std::forward<TupleType>(t), f, std::integral_constant<size_t, I + 1>());
}
template<typename TupleType, typename FunctionType>
void for_each(TupleType&& t, FunctionType f)
{
for_each(std::forward<TupleType>(t), f, std::integral_constant<size_t, 0>());
}
Usage (with std::tuple):
auto some = std::make_tuple("I am good", 255, 2.1);
for_each(some, [](const auto &x) { std::cout << x << std::endl; });
Usage (with std::array):
std::array<std::string,2> some2 = {"Also good", "Hello world"};
for_each(some2, [](const auto &x) { std::cout << x << std::endl; });
DEMO
General idea: as in the solution of T.C., start with an index I=0 and go up to the size of the tuple. However, here it is done not per variadic expansion but one-at-a-time.
Explanation:
The first overload of for_each is called if I is equal to the size of the tuple. The function then simply does nothing and such end the recursion.
The second overload calls the function with the argument std::get<I>(t) and increases the index by one. The class std::integral_constant is needed in order to resolve the value of I at compile time. The std::enable_if SFINAE stuff is used to help the compiler separate this overload from the previous one, and call this overload only if the I is smaller than the tuple size (on Coliru this is needed, whereas in Visual Studio it works without).
The third starts the recursion with I=0. It is the overload which is usually called from outside.
EDIT: I've also included the idea mentioned by Yakk to additionally support std::array and std::pair by using a general template parameter TupleType instead of one that is specialized for std::tuple<Ts ...>.
As TupleType type needs to be deduced and is such a "universal reference", this further has the advantage that one gets perfect forwarding for free. The downside is that one has to use another indirection via typename std::remove_reference<TupleType>::type, as TupleType might also be a deduced as a reference type.

Unexpected result when trying to compose a curried lambda with another lambda

I am toying with C++11 lambdas and was trying to mimick some function from the functional module of the D programming language. I was actually trying to implement curry and compose. Here is the main that I am trying to get working:
int main()
{
auto add = [](int a, int b)
{
return a + b;
};
auto add5 = curry(add, 5);
auto composed = compose(add5, add);
// Expected result: 25
std::cout << composed(5, 15) << std::endl;
}
The problem is that I don't get the same result from g++ and clang++. I get:
35 with g++ 4.8.1
25 with g++ 4.8.2
25 with g++ 4.9
32787 with clang++ 3.5 (trunk used with Coliru)
g++ 4.8.2 and 4.9 give me the expected result. The results obtained from g++ 4.8.1 and clang 3.5 do not depend on the value passed to curry. I first thought that this may be a compiler bug, but it is more likely that I have an error in my code.
Here is my implementation of curry:
template<typename Function, typename First, std::size_t... Ind>
auto curry_impl(const Function& func, First&& first, indices<Ind...>)
-> std::function<
typename function_traits<Function>::result_type(
typename function_traits<Function>::template argument_type<Ind>...)>
{
return [&](typename function_traits<Function>::template argument_type<Ind>&&... args)
{
return func(
std::forward<First>(first),
std::forward<typename function_traits<Function>::template argument_type<Ind>>(args)...
);
};
}
template<typename Function, typename First,
typename Indices=indices_range<1, function_traits<Function>::arity>>
auto curry(Function&& func, First first)
-> decltype(curry_impl(std::forward<Function>(func), std::forward<First>(first), Indices()))
{
using FirstArg = typename function_traits<Function>::template argument_type<0>;
static_assert(std::is_convertible<First, FirstArg>::value,
"the value to be tied should be convertible to the type of the function's first parameter");
return curry_impl(std::forward<Function>(func), std::forward<First>(first), Indices());
}
And here is my implementation of compose (note that I only wrote a binary compose while the D one is variadic):
template<typename First, typename Second, std::size_t... Ind>
auto compose_impl(const First& first, const Second& second, indices<Ind...>)
-> std::function<
typename function_traits<First>::result_type(
typename function_traits<Second>::template argument_type<Ind>...)>
{
return [&](typename function_traits<Second>::template argument_type<Ind>&&... args)
{
return first(second(
std::forward<typename function_traits<Second>::template argument_type<Ind>>(args)...
));
};
}
template<typename First, typename Second,
typename Indices=make_indices<function_traits<Second>::arity>>
auto compose(First&& first, Second&& second)
-> decltype(compose_impl(std::forward<First>(first), std::forward<Second>(second), Indices()))
{
static_assert(function_traits<First>::arity == 1u,
"all the functions passed to compose, except the last one, must take exactly one parameter");
using Ret = typename function_traits<Second>::result_type;
using FirstArg = typename function_traits<First>::template argument_type<0>;
static_assert(std::is_convertible<Ret, FirstArg>::value,
"incompatible return types in compose");
return compose_impl(std::forward<First>(first), std::forward<Second>(second), Indices());
}
The class function_trait is used to get the arity, the return type and the type of the arguments of a lambda. This code heavily relies on the indices trick. Since I don't use C++14, I don't use std::index_sequence but an older implementation under the name indices. indices_range<begin, end> is an indices sequence corresponding to the range [begin, end). You can find the implementation of these helper metafunctions (as well as curry and compose) on the online version of the code, but they are less meaningful in this problem.
Do I have a bug in the implementation of curry and/or compose or are the bad results (with g++ 4.8.1 and clang++ 3.5) due to compiler bugs?
EDIT: You may find the code above not quite readable. So, here are versions of curry and compose that are exactly the same, but use alias templates to reduce the boilerplate. I also removed the static_asserts; while they may be helpful information, that's just too much text for the question and they do not play a part in the problem at hand.
template<typename Function, typename First, std::size_t... Ind>
auto curry_impl(const Function& func, First&& first, indices<Ind...>)
-> std::function<
result_type<Function>(
argument_type<Function, Ind>...)>
{
return [&](argument_type<Function, Ind>&&... args)
{
return func(
std::forward<First>(first),
std::forward<argument_type<Function, Ind>>(args)...
);
};
}
template<typename Function, typename First,
typename Indices=indices_range<1, function_traits<Function>::arity>>
auto curry(Function&& func, First first)
-> decltype(curry_impl(std::forward<Function>(func), std::forward<First>(first), Indices()))
{
return curry_impl(std::forward<Function>(func), std::forward<First>(first), Indices());
}
template<typename First, typename Second, std::size_t... Ind>
auto compose_impl(const First& first, const Second& second, indices<Ind...>)
-> std::function<
typename result_type<First>(
typename argument_type<Second, Ind>...)>
{
return [&](argument_type<Second, Ind>&&... args)
{
return first(second(
std::forward<argument_type<Second, Ind>>(args)...
));
};
}
template<typename First, typename Second,
typename Indices=make_indices<function_traits<Second>::arity>>
auto compose(First&& first, Second&& second)
-> decltype(compose_impl(std::forward<First>(first), std::forward<Second>(second), Indices()))
{
return compose_impl(std::forward<First>(first), std::forward<Second>(second), Indices());
}
As I believe others have mentioned in your comments, the issues relating to your code are lifetime issues. Note that you're passing the second parameter, 5, to curry as an rvalue:
auto add5 = curry(add, 5);
Then, in the invocation of the curry function, you're creating a copy of that variable on the stack as one of the parameters:
auto curry(Function&& func, First first)
Then, in your call to curry_impl you pass a reference to the first that won't exist once your call to curry completes. As the lambda you're producing uses a reference to a variable that no longer exists, you get undefined behavior.
To fix the problem you're experiencing, simply change the prototype of curry to use a universal reference to first and make sure you don't pass rvalues to curry:
template<typename Function, typename First,
typename Indices=indices_range<1, function_traits<Function>::arity>>
auto curry(Function&& func, First&& first)
-> decltype(curry_impl(std::forward<Function>(func), std::forward<First>(first), Indices()))
{
using FirstArg = typename function_traits<Function>::template argument_type<0>;
static_assert(std::is_convertible<First, FirstArg>::value,
"the value to be tied should be convertible to the type of the function's first parameter");
return curry_impl(std::forward<Function>(func), std::forward<First>(first), Indices());
}
Then in main:
int foo = 5;
auto add5 = curry(add, foo);
Of course, limiting yourself to lvalue expressions is a pretty huge problem with the interface, so it's worth mentioning that if you planned on utilizing this outside of an exercise, it would be a good idea to provide an interface where rvalues can be used.
Then again, I would change it so that the resulting functor owns copies of its components as std::bind does. I know I would be a little perplexed if the following code didn't work:
std::function<int(int)> foo()
{
std::function<int(int, int)> add = [](int a, int b)
{
return a + b;
};
return curry(add, 5);
}
Edit: I see now that some versions of gcc still require the values to be captured by value into the resulting lamba. GCC 4.9.0 20131229 is the build I tested it on which works fine.
Edit #2: specified correct usage per Xeo

Using an array of lambda arguments

I'm playing around with C++14 lambdas (well just lambdas in general really) and I have a function (pipeline) I'm trying to write. The premise is that it'll take a unit lambda and an array of unary lambdas that it'll then run on the unit and produce a new unit to send into the next in the pipeline until you get through the last lambda and return the final unit. my current code is:
auto pipeline = [](auto u, auto callbacks[]){
for(int i = 0; i<sizeof(callbacks)/sizeof(callbacks[0]);i++){
u = bind(u,callbacks[i]);
}
return u;
};
The current issue is that clang is kicking back on the array saying:
testFuture.cpp:183:111: error: no matching function for call to object of type 'func::<lambda at ./func.hpp:30:19>'
cout<<"pipeline(unit(10),{addf(4),curry(mul,2)}):"<<bind(unit(bind(unit(10))(addf(4))))(curry(mul,2))<<"|"<<pipeline(unit(10),{{addf(4),curry(mul,2)}})()<<endl;
^~~~~~~~
./func.hpp:30:19: note: candidate template ignored: couldn't infer template argument '$auto-0-1'
auto pipeline = [](auto u, auto callbacks[]){
^
1 error generated.
Is this simply not possible with lambdas? Do I need to whip out std::function? Am I just going about this the wrong way?
Taking a step back, you’re attempting to perform a (left) fold over a sequence of values. Because in C++ each closure has a unique type, you want to make that fold over a tuple, not an array. As an added benefit, we will be more general and accept functors with any return type, which we couldn’t if e.g. we used std::function to emulate arrow types.
#include <utility> // std::forward, std::integer_sequence
#include <type_traits> // std::remove_reference_t
#include <tuple> // tuple protocol, e.g. std::get, std::tuple_size
namespace detail {
template<typename Functor, typename Zero, typename Tuple, typename Int>
Zero foldl(Functor&&, Zero&& zero, Tuple&&, std::integer_sequence<Int>)
{ return std::forward<Zero>(zero); }
template<typename Functor, typename Zero, typename Tuple, typename Int, Int Index, Int... Indices>
decltype(auto) foldl(Functor&& functor, Zero&& zero, Tuple&& tuple, std::integer_sequence<Int, Index, Indices...>)
{ return detail::foldl(
functor
, functor(std::forward<Zero>(zero), std::get<Index>(std::forward<Tuple>(tuple)))
, std::forward<Tuple>(tuple)
, std::integer_sequence<Int, Indices...> {}); }
} // detail
template<typename Functor, typename Zero, typename Tuple>
decltype(auto) foldl(Functor&& functor, Zero&& zero, Tuple&& tuple)
{
return detail::foldl(
std::forward<Functor>(functor)
, std::forward<Zero>(zero)
, std::forward<Tuple>(tuple)
, std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>()
);
}
You haven’t told us what bind is supposed to achieve, but here’s an example involving reverse composition of functions. (Included is a limited implementation of integer_sequence and friends as they don’t appear to be available on Coliru — type traits aliases are missing as well.)