Search code examples
c++c++11templatestype-deduction

decltype of function parameter


Is it possible to deduce the type of a function parameter? For example, if I have:

void foo(int a);

I would like to deduce the type int as the type of foo's first parameter. A possible use could be:

foo( static_cast< decltype(/* ??? foo's first param ??? */) >(value) );

In this related question, the answers exploit having a member with the same type for deduction, so it does not directly deduce the function parameter type.


Solution

  • Is it possible to deduce the type of a function parameter?

    Sure.

    With a type traits, by example (argType)

    template <typename>
    struct argType;
    
    template <typename R, typename A>
    struct argType<R(A)>
     { using type = A; };
    
    
    void foo(int a)
     { }
    
    int main()
     {
       long value = 1L;
    
       foo( static_cast<typename argType<decltype(foo)>::type>(value) );
     }
    

    If you're interrested in a little more generic solution, the following example show how create and use a type traits to detect the return type or the n-th argument type

    #include <string>
    
    template <std::size_t N, typename T0, typename ... Ts>
    struct typeN
     { using type = typename typeN<N-1U, Ts...>::type; };
    
    template <typename T0, typename ... Ts>
    struct typeN<0U, T0, Ts...>
     { using type = T0; };
    
    template <std::size_t, typename>
    struct argN;
    
    template <std::size_t N, typename R, typename ... As>
    struct argN<N, R(As...)>
     { using type = typename typeN<N, As...>::type; };
    
    template <typename>
    struct returnType;
    
    template <typename R, typename ... As>
    struct returnType<R(As...)>
     { using type = R; };
    
    long bar (int a, std::string const &)
     { return a; }
    
    int main()
     {
       long         valI = 1L;
       char const * valS = "abc";
    
       bar( static_cast<typename argN<0U, decltype(bar)>::type>(valI),
            static_cast<typename argN<1U, decltype(bar)>::type>(valS) );
    
       static_assert(
          std::is_same<long,
                       typename returnType<decltype(bar)>::type>::value, "!");
     }