Returning perfectly forwarded args from lambda C++14 - c++

auto myLambda = [](auto&& val_)
{
val_ *= 2;
return std::forward<decltype(val_)>(val_);
};
int someNum = 55;
auto&& ret1 = myLambda(3);
auto&& ret2 = myLambda(someNum);
I am trying out advanced features of lambda however, I am unable to return an argument via perfect forwarding. Both types of ret1 and ret2 variables expand to int&&. I am pretty sure I can perfectly forward the args to another function, from inside the lamda object. I tried to change the return type to decltype(auto) without luck. Can we say lambdas cannot return via perfect forwarding with confidence?
If I were to write a templated function for this , I could achieve perfect forwarding.

The lambda will not return a reference to val_ (it will only return the value of val_). If you want to do this, you must provide the return type explicitly:
auto myLambda = [](auto&& val_) -> decltype(val_)
{
val_ *= 2;
return std::forward<decltype(val_)>(val_);
};

Related

Why Can't I constexpr a bind?

So say that I want to make some constexpr functors, I though I could do this using bind. Is there something I'm missing? Why can't bind return a constexpr?
Given:
struct foo {
int b() const { return _b; }
int a() const { return _a; }
int r() const { return _r; }
const int _b;
const int _a;
const int _r;
};
I want to:
constexpr auto sumB = bind(plus<int>(), placeholders::_1, bind(&foo::b, placeholders::_2));
constexpr auto sumA = bind(plus<int>(), placeholders::_1, bind(&foo::a, placeholders::_2));
constexpr auto sumR = bind(plus<int>(), placeholders::_1, bind(&foo::r, placeholders::_2));
Is there something I could do to make this work?
There is no technical obstacle to making bind constexpr; for example, the Sprout C++ Libraries have a constexpr-enabled bind.
However, implementations are not permitted to add constexpr to function signatures where it is not specified in the Standard, and there has not yet been any proposal to add constexpr to bind that I am aware of (Which parts of the C++14 Standard Library could be and which parts will be made constexpr?). It is fairly unlikely that one would be forthcoming, since bind is mostly superseded by lambda expressions, which as of C++17 are automatically constexpr:
constexpr auto sumB = [](int x, foo const& y) { return x + y.b(); };
Well, we don't know what std::bind returns. It could probably be made to work but there is nothing mandated to make it work (nothing is defined as constexpr in std::bind's specification).
On thing you can do though, if you have access to C++17, is to use a lambda. In C++17 the operator() of the lambda will be marked constexpr by default allowing you to do something like
constexpr auto sumB = [](auto val, auto obj) { return val + obj.b(); };
constexpr auto sumA = [](auto val, auto obj) { return val + obj.a(); };
constexpr auto sumR = [](auto val, auto obj) { return val + obj.r(); };
Live Example

Is there a std::function type or similar for lambda with auto parameter?

When I assign a lambda to an explicitly typed variable (for example when it is recursive, to capture the function in itself), I use std::function.
Consider this silly "bit counting" function as an example:
std::function<int(int)> f;
f = [&f](int x){ return x ? f(x/2)+1 : 0; };
What about the case when we use an auto parameter to generalize x, as introduced in C++14 generic lambda?
std::function<int(???)> f;
f = [&f](auto x){ return x ? f(x/2)+1 : 0; };
Obviously, I can't place auto in the function type parameters.
Is there a possibility to define a functor class generically enough to cover the exact case above, but still using lambda for the function definition?
(Don't over-generalize this, only accept a single auto parameter and hard-code the return value.) The use case would be for the scenario like above: capturing the function in itself by reference for recursive calls.
You can create a lambda that calls itself by passing it to itself as a parameter:
auto f = [](auto self, auto x) -> int {
return x ? self(self, x / 2) + 1 : 0;
};
std::cout << f(f, 10);
You can then capture that lambda in another lambda, so you don't have to worry about passing it to itself:
auto f2 = [&f](auto x) {
return f(f, x);
};
std::cout << f2(10);
Here is a quick y-combinator based recursive engine:
template<class F>
struct recursive_t {
F f;
// note Self must be an lvalue reference. Things get
// strange if it is an rvalue:
// invoke makes recursive ADL work a touch better.
template<class Self, class...Args>
friend auto invoke( Self& self, Args&&...args )
-> decltype( self.f( self, std::declval<Args>()... ) )
{
return self.f( self, std::forward<Args>(args)... );
}
// calculate return type using `invoke` above:
template<class Self, class...Args>
using R = decltype( invoke( std::declval<Self>(), std::declval<Args>()... ) );
template<class...Args>
R<recursive_t&, Args...> operator()(Args&&...args)
{
return invoke( *this, std::forward<Args>(args)... );
}
template<class...Args>
R<recursive_t const&, Args...> operator()(Args&&...args)const
{
return invoke( *this, std::forward<Args>(args)... );
}
};
template<class F>
recursive_t< std::decay_t<F> > recurse( F&& f )
{
return {std::forward<F>(f)};
}
now you can do:
auto f = recurse( [](auto&& f, auto x){ return x ? f(x/2)+1 : 0; } );
and you get a recursive lambda that doesn't have a & capture (which limits its use to the current scope).
Capturing a std::function by reference means your lambda's lifetime is the current scope, and every recursive call requires going over type erasure (blocking any possible optimization, like tail-recursion, over the recursive call). The same holds true of other similar solutions.
The use of recursive_t is required rather than using a lambda, because a lambda cannot name itself within itself.
Live example.
A lambda based version is somewhat simpler in implementation. Note that you'd need a different type function for mutable and immutable lambdas:
template<class F>
auto recurse( F&& f ) {
return [f=std::forward<F>(f)](auto&&...args){
return f(f, decltype(args)(args)...);
};
};
The recursive_t works like:
auto fib = recurse( [](auto&& fib, int x){ if (x<2) return 1; return fib(x-1)+fib(x-2); } );
the lambda version works like:
auto fib = recurse( [](auto&& self, int x){ if (x<2) return 1; return self(self, x-1)+self(self,x-2); } );
which I, personally, find more awkward.
It is also harder to describe the type of recurse. For the recursive_t version, recurse is of type:
((A->B)->A->B)->(A->B)
which is awkward, but a finite type.
The lambda version is trickier. The type of the function argument to recursive is of type:
F:= F->A->B
which is annoyingly infinite, and then recurse is of type
F->A->(A->B)
which inherits the infinity.
Anyhow, the recurse return value can then be stored in a mundane std::function, or not stored in any type-erased container.

Enable C++14 Intel Compiler

I'm using Intel C++ Compiler version 15.0.0.108 Build 20140726 and I can't use some C++14 features like "decltype(auto), return type deduction for normal functions" declared support in here
If I do something like:
std::for_each(vector.begin(), vector.end(), [] (auto value) {});
Then I got this error:
error: "auto" is not allowed here
I'm compiling using this:
icl /FA /EHs program.cpp
The feature you're trying to use is called a generic (polymorphic) lambda expression from N3649 and the table you linked shows that support has not been added yet. However, the feature(s) you think you're using, "decltype(auto), return type deduction for normal functions" from N3638 do have support.
A generic lambda looks like:
[](auto a) { return a; }
Return type deduction for normal functions looks like:
auto func() { return 42; } // deduced to be int
The semantics for decltype(auto) are described in the following example from n3638:
If the placeholder is the decltype(auto) type-specifier, the declared
type of the variable or return type of the function shall be the
placeholder alone. The type deduced for the variable or return type is
determined as described in 7.1.6.2, as though the initializer had been
the operand of the decltype. [ Example:
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(auto) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype(auto) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(auto) x5d = f(); // decltype(x5d) is int&&
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i; // decltype(x7a) is int*
decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)
— end example ]

automatic decay of lambda to function pointer when passing to template function

Is there a way to make a lambda decay to a pointer, without explicitly casting to the right signature? This would tidy some code:
template<typename T> T call(T(*func)()){ return func(); }
int ptr(){ return 0; }
int main(){
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; }));
auto ret3 = call([]{ return 0; }); //won't compile
}
It's evident that a call to call works only if the lambda decays to a pointer, but I'm guessing that that can happen only after the right function overload/template is chosen. Unfortunately I can only think of solutions that involve templates to make a lambda with any signature decay, so I'm back to square one.
You can change your lambda to use the unary + operator: +[]{ return 0; }
This works because unary plus can be applied to pointers, and will trigger the implicit conversion to function pointer.
Why would you unnecessarily constrain yourself to function pointers without defaulted arguments and lambdas without captures, completely ruling out the huge family of functors (e.g. std::function, any results of std::bind and everything else that has a suitable operator())?
Better just broaden your function signature:
template <typename F>
auto call(F func) -> decltype(func()) {
return func();
}
int ptr() { return 0; }
int g(int i = 0) {return i;}
int main() {
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; })); //tedious, but works
auto ret3 = call([]{ return 0; }); //ok now.
auto ret4 = call(g); //ok now!
int i = 42;
auto ret5 = call([=]{return i;}); //works, too!
auto ret6 = call(std::bind(g, i)); //and so on...
}
As a TL;DR; implementation of the #Simple proposal, I have write a simple test as follow:
SCENARIO("decay_equiv", "")
{
auto callback = +[](struct mosquitto *, void *,
const struct mosquitto_message *)->void{};
typedef typename std::is_same<
typename std::decay<decltype(callback)>::type,
typename std::decay<void (*)(struct mosquitto *, void *, const struct mosquitto_message *)>::type
>::type s;
std::cout << s::value << std::endl;
}
Try it removing the + in the callback definition and everything stop to work.

C++11 auto: what if it gets a constant reference?

Please take a look at the following simple code:
class Foo
{
public:
Foo(){}
~Foo(){}
Foo(const Foo&){}
Foo& operator=(const Foo&) { return *this; }
};
static Foo g_temp;
const Foo& GetFoo() { return g_temp; }
I tried to use auto like this:
auto my_foo = GetFoo();
I expected that my_foo will be a constant reference to Foo, which is the return type of the function. However, the type of auto is Foo, not the reference. Furthermore, my_foo is created by copying g_temp. This behavior isn't that obvious to me.
In order to get the reference to Foo, I needed to write like this:
const auto& my_foo2 = GetFoo();
auto& my_foo3 = GetFoo();
Question: Why does auto deduce the return type of GetFoo as an object, not a reference?
Read this article: Appearing and Disappearing consts in C++
Type deduction for auto variables in C++0x is essentially the same as
for template parameters. (As far as I know, the only difference
between the two is that the type of auto variables may be deduced from
initializer lists, while the types of template parameters may not be.)
Each of the following declarations therefore declare variables of type
int (never const int):
auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;
During type deduction for template parameters and auto variables, only
top-level consts are removed. Given a function template taking a
pointer or reference parameter, the constness of whatever is pointed
or referred to is retained:
template<typename T>
void f(T& p);
int i;
const int ci = 0;
const int *pci = &i;
f(i); // as before, calls f<int>, i.e., T is int
f(ci); // now calls f<const int>, i.e., T is const int
f(*pci); // also calls f<const int>, i.e., T is const int
This behavior is old news, applying as it does to both C++98 and
C++03. The corresponding behavior for auto variables is, of course,
new to C++0x:
auto& a1 = i; // a1 is of type int&
auto& a2 = ci; // a2 is of type const int&
auto& a3 = *pci; // a3 is also of type const int&
auto& a4 = pcs->i; // a4 is of type const int&, too
Since you can retain the cv-qualifier if the type is a reference or pointer, you can do:
auto& my_foo2 = GetFoo();
Instead of having to specify it as const (same goes for volatile).
Edit: As for why auto deduces the return type of GetFoo() as a value instead of a reference (which was your main question, sorry), consider this:
const Foo my_foo = GetFoo();
The above will create a copy, since my_foo is a value. If auto were to return an lvalue reference, the above wouldn't be possible.

Resources