Limitations of std::result_of for lambdas in C++14

Viewed 106

I have a working piece of C++17 code that I would like to port to C++14 (project's constraints). The code allocates a functor on the heap, based on the lambda returned by a provider.

decltype(auto) fun_provider(std::string msg)                                                                                                                                                                                                                                      
{
    return [msg](){ std::cout << msg << std::endl; };
}

int main()
{
    auto fun = std::make_unique<
                    std::invoke_result_t<decltype(fun_provider), std::string>
                   >(fun_provider("Provided functor"));
    (*fun.get())()
}
// output: "Provided functor"

The point is, it avoids hardcoding lambda type as std::function<void()>. Up to my best knowledge, the closure type is unspecified and such construction would imply unnecessary copy of the closure object (hope that's correct).

I would like to achieve the same goal with C++14, is it possible? I tried few constructions with std::result_of and/or decltype but didn't succeed so far.

3 Answers

How about routing fun_provider's return value through another pass of template deduction?

template <class T>
auto to_unique(T&& orig) {
    using BaseType = std::remove_cv_t<std::remove_reference_t<T>>;
    return std::make_unique<BaseType>(std::forward<T>(orig));
}

int main()
{
    auto fun = to_unique(fun_provider("Provided functor"));
    (*fun.get())();
}

Is this approach not viable?

    auto fun = std::make_unique<
                    decltype(fun_provider(std::declval<std::string>()))
                   >(fun_provider("Provided functor"));

The use of std::declval isn't even necessary; std::string{} instead of std::declval<std::string>() is just fine.

Just for the sake of completeness and to answer the original question.

The correct solution using std::result_of_t would look like this:

auto fun = std::make_unique<
              std::result_of_t<decltype(&fun_provider)(std::string)>
             >(fun_provider("Provided functor"));
Related