Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::result_of not work with lambdas?

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.

like image 594
user2059893 Avatar asked Feb 19 '15 23:02

user2059893


People also ask

Why is std :: Result_of deprecated?

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);

How do you call a lambda in C++?

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.

When should you use lambda functions C++?

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.

What is the type of a lambda?

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.


2 Answers

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();
}
like image 171
Praetorian Avatar answered Sep 28 '22 07:09

Praetorian


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();
}
like image 38
Paul Fultz II Avatar answered Sep 28 '22 08:09

Paul Fultz II