Quantcast
Channel: What are the type conversion rules for parameters and return values of lambdas? - Stack Overflow
Viewing all articles
Browse latest Browse all 5

Answer by Andrew for What are the type conversion rules for parameters and return values of lambdas?

$
0
0

The assignment operator is defined to have the effect:

function(std::forward<F>(f)).swap(*this);

(14882:2011 20.8.11.2.1 par. 18)

The constructor that this references,

template <class F> function(F f);

requires:

F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument type ArgTypes and return type R.

where Callable is defined as follows:

A callable object f of type F is Callable for argument types ArgTypes and return type R if the expression INVOKE(f, declval<ArgTypes>()..., R), considered as an unevaluated operand (Clause 5), is well formed (20.8.2).

INVOKE, in turn, is defined as:

  1. Define INVOKE(f, t1, t2, ..., tN) as follows:

    • ... cases for handling member functions omitted here ...
    • f(t1, t2, ..., tN) in all other cases.
  2. Define INVOKE(f, t1, t2, ..., tN, R) as static_cast<void>(INVOKE(f, t1, t2, ..., tN)) if R is cvvoid, otherwise INVOKE(f, t1, t2, ..., tN) implicitly converted to R.

Since the INVOKE definition becomes a plain function call, in this case, the arguments can be converted: If your std::function<void(const int&)> accepts a const int& then it can be converted to an int for the call. The example below compiles with clang++ -std=c++14 -stdlib=libc++ -Wall -Wconversion:

int main() {    std::function<void(const int& i)> f;    f = [](int i) -> void { std::cout << i << std::endl; };    f(2);    return 0;}

The return type (void) is handled by the static_cast<void> special-case for the INVOKE definition.

Note, however, that at the time of writing the following generates an error when compiled with clang++ -std=c++1z -stdlib=libc++ -Wconversion -Wall, but not when compiled with clang++ -std=c++1z -stdlib=libstdc++ -Wconversion -Wall:

int main() {    std::function<void(const int& i)> f;    f = [](int i) -> int { std::cout << i << std::endl; return i;};    f(2);    return 0;}

This is due to libc++ implementing the behaviour as specified in C++14, rather than the amended behaviour described above (thanks to @Jonathan Wakely for pointing this out). @Arunmu describes the libstdc++ type trait responsible for the same thing in his post. In this regard, implementations may behave slightly differently when handling callables with void return types, depending on whether they implement C++11, 14, or something newer.


Viewing all articles
Browse latest Browse all 5

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>