20

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.

max66
  • 65,235
  • 10
  • 71
  • 111
Jake Cobb
  • 1,811
  • 14
  • 27

2 Answers2

18

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, "!");
 }
max66
  • 65,235
  • 10
  • 71
  • 111
  • @NoSenseEtAl - Yes, but lambdas aren't functions. When you have a lambda that is convertible to a function pointer, you can use something as `decltype(+baz)`, (where `baz` is the convertible lambda) but you have to modify `returnType` and `argN` to works (also?) with function pointers. – max66 Apr 03 '19 at 07:47
9

A slightly generalized version of the answer by @max66:

template <typename> struct FirstArgument;

template <typename R, typename A, typename... Args>
struct FirstArgument<R(A, Args...)>
{
   using type = A;
};

template <typename T>
using first_agument_t = typename FirstArgument<T>::type;

void foo(int a){ }

void bar(int a, double b){ }

int main()
{
   long value = 1L;
   foo(static_cast<first_agument_t<decltype(foo)>>(value) );
   bar(static_cast<first_agument_t<decltype(bar)>>(value), 0);
}
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I don't quite understand the syntax when the `T` in `first_agument_t` is deduced into `R` `A` `Args` in `FirstArgument`, any link to this syntax? – Felix F Xu Jun 06 '23 at 14:15