Search code examples
c++undefined-behaviorstd-function

Can I assign a callable to a std::function with a different return type?


I want to store a function inside a std::function. I don't care about the return value when calling this stored function, so the std::function just returns void.

Is there any undefined behavior when the stored function gets called?

Take the following example as a reference, where the function is a lambda returning an int (Link to run):

#include <iostream>
#include <functional>
std::function<void(void)> f;
int main()
{
    f = []() -> int { std::cout << "Returning int\n";  return 0; };
    f(); // Is this UB in any way?
    return 0;
}

The question applies not only to lambdas, but to any callable, such as member functions, free functions, etc.


Solution

  • Ignoring the return result is explicitly allowed.

    You are using the template< class F > function& operator=( F&& f ); overload of operator=, which has the requirement:

    This operator does not participate in overload resolution unless f is Callable for argument types Args... and return type R.

    Which is

    INVOKE<R>(f, std::declval<ArgTypes>()...) is well-formed in unevaluated context.

    And std::function<R(Args...>::operator()(Args... args) is similarly defined as doing INVOKE<R>(f, std::forward<Args>(args)...), returning nothing in the case R is void.

    The exposition-only operation INVOKE<R>(f, arg_0, arg_1, arg_2, ..., arg_N) is defined as follows:

    • If R is (possibly cv-qualified) void

      • static_cast<void>(INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N)).

    I.e. it explicitly discards the result by casting to void