I managed to reduce my case to the following simplest piece of code:
#include <type_traits>
auto call(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
return f();
}
int main()
{
return call([] { return 0; });
}
Neither gcc-4.9.2 and gcc-5.0.0 compile!
Both think that "call" should be returning a lambda function! The don't figure out that "call" returns an int.
Is this a bug in the compiler or is my c++ off? Many thanks.
F(Args...) is a function type with Args... being the argument types and F being the return type. As such, std::result_of suffers from several quirks that led to its deprecation in favor of std::invoke_result in C++17: F cannot be a function type or an array type (but can be a reference to them);
A lambda is also just a function object, so you need to have a () to call it, there is no way around it (except of course some function that invokes the lambda like std::invoke ). If you want you can drop the () after the capture list, because your lambda doesn't take any parameters.
50: Use a lambda when a function won't do (to capture local variables, or to write a local function) The difference in the usage of functions and lambda functions boils down to two points. You can not overload lambdas. A lambda function can capture local variables.
A type lambda lets one express a higher-kinded type directly, without a type definition. For instance, the type above defines a binary type constructor, which maps arguments X and Y to Map[Y, X] . Type parameters of type lambdas can have bounds, but they cannot carry + or - variance annotations.
Your code's not valid C++ because function parameter types cannot be auto
, this syntax has been proposed for Concepts Lite and may become part of the language in the future.
result_of
needs a call expression from which it will deduce the return type.
Fixing both of these, your code becomes
template<typename F>
auto call(F const& f) -> typename std::result_of<decltype(f)()>::type
// or typename std::result_of<F()>::type
{
return f();
}
Or you could just use
template<typename F>
auto call(F const& f) -> decltype(f())
{
return f();
}
Live demo
I think your original code should compile if you fix the result_of
expression, but it doesn't on gcc-4.9 or 5.0; maybe this is a bug with the gcc extension that allows parameter types to be auto
// This fails to compile
auto call3(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
return f();
}
Thats not the way you call std::result_of
, it should be:
auto call(const auto& f) -> typename std::result_of<decltype(f)()>::type
{
return f();
}
Or even simpler you could just write:
auto call(const auto& f) -> decltype(f())
{
return f();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With