Search code examples
c++c++17signaturecallabletemplate-argument-deduction

C++ 17: Deduce signature from Callable in a template


If and how is it possible to deduce the signature type from any callable in C++17? Snippet:

template <typename T>
struct MyFunction;

template <typename R, typename... Args>
struct MyFunction<R(Args...)>
{
};

template <typename Callable>
auto deduceSignature(Callable&& c)
{
    // using Signature = ???;
    // return MyFunction<Signature>{ ???};}
}

I would like to use use class template argument deduction in the return statement. In client code I want to write this then:

std::int8_t freeFunction(std::int8_t x)
{
    return x;
}

auto c1 = deduceSignature(&freeFunction);
auto c2 = deduceSignature([](std::int8_t x){
    return x;
});

Solution

  • std::function can be constructed from any callable, and can deduce the signature (since c++17). We can use this to make a type trait that extracts the signature.

    #include <functional>
    
    template <typename T>
    struct get_signature;
    
    template <typename R, typename... Args>
    struct get_signature<std::function<R(Args...)>> {
        using type = R(Args...);
    };
    
    template <typename Callable>
    auto deduceSignature(Callable&& c)
    {
        using Signature = typename get_signature<decltype(std::function{c})>::type;
    }
    
    int main() {
        deduceSignature([](int a){return 5;});
    }