Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is possible to deduce function argument type in C++?

Having the function definition:

void f(int) { }

I want to define:

int a;

but if the function definition changes to:

void f(double) { }

the variable definition must become:

double a;

that is, the type of "a" must be the same of the first argument of the "f" function. I need something like the following:

decltype_of_argument<f, 0> a;

Is it possible in C++?

like image 934
user3459257 Avatar asked Mar 25 '14 10:03

user3459257


People also ask

What is the argument of a function in C?

The values that are declared within a function when the function is called are known as an argument. These values are considered as the root of the function that needs the arguments while execution, and it is also known as Actual arguments or Actual Parameters.

What is argument type in C?

An argument refers to values that are passed within a function when the calling of a function takes place. Furthermore, specifying argument data types is important for C++ programming. Moreover, C++ supports three types of argument data types – pass by value, pass by reference, and pass by pointer.

How arguments are used in function?

In mathematics, an argument of a function is a value provided to obtain the function's result. It is also called an independent variable. , is called a unary function. A function of two or more variables is considered to have a domain consisting of ordered pairs or tuples of argument values.


2 Answers

You can get the type by template metaprogramming:

template <class F> struct ArgType;

template <class R, class T> 
struct ArgType<R(*)(T)> {
  typedef T type;
}; 

void f(int) {}

#include <type_traits>
#include <iostream>

int main() {

  // To prove
  std::cout << std::is_same< ArgType<decltype(&f)>::type, int >::value << '\n';

  // To use
  ArgType<decltype(&f)>::type a;
}

Depending on where you want to use it you'd need to specialize this litte template for other callable entities such as member function poitners, functions with more arguments, functors etc. There are more sophisitcated approaches in the Boost libraries, see e.g. https://stackoverflow.com/a/15645459/1838266

Caveat: all these utilities work only if the name of the function/callable is unambiguously mapped to one single function signature. If a function is overloaded or if a functor has more than one operator(), the right function/operator has to be picked by explicitly casting to the right signature, which makes finding out part of the signature via the template pretty useless. This applies in a certain way to templates as well, although getting the signature of an explicitly secialized callable might still be useful, e.g.:

template <unsigned N, class F> struct ArgType; //somewhat more sophisitcated 

template <class T> void f(int, T);

ArgType<0, decltype(&f<double>)> //int    - ArgType has it's use here
ArgType<1, decltype(&f<double>)> //double - here it's useless...
like image 141
Arne Mertz Avatar answered Sep 23 '22 03:09

Arne Mertz


It depends on what you want to do, where that variable shall be used. If it is in the function a template might be a good choice:

template<typename T>
void foo(T ) {
    T a;
}

Alternatively if you are outside the function and have the requirement to really know this you can use Boost.TypeTraits, i.e. function_traits<void (int)>::arg1_type will give int

like image 32
johannes Avatar answered Sep 22 '22 03:09

johannes