Как можно вывести тип аргумента функции в С++?
Имея определение функции:
void f(int) { }
Я хочу определить:
int a;
но если определение функции изменится на:
void f(double) { }
определение переменной должно быть:
double a;
то есть тип "a" должен быть тем же самым из первого аргумента функции "f".
Мне нужно что-то вроде следующего:
decltype_of_argument<f, 0> a;
Возможно ли это в С++?
Ответы
Ответ 1
Вы можете получить тип путем метапрограммирования шаблонов:
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;
}
В зависимости от того, где вы хотите его использовать, вам нужно будет специализировать этот шаблон litte для других вызываемых объектов, таких как функции-члены-члены, функции с большим количеством аргументов, функторы и т.д. В библиотеках Boost есть более изощренные подходы, см., например, fooobar.com/questions/387125/...
Предостережение: все эти утилиты работают только в том случае, если имя функции/вызываемого однозначно отображается на одну подпись функции. Если функция перегружена или если функтор имеет более одного operator()
, то правильный оператор функции/должен быть выбран путем явного нажатия на правую подпись, что делает поиск части сигнатуры через шаблон довольно бесполезным. Это также относится к шаблонам определенным образом, хотя получение подписи явно разделяемого вызова может быть полезным, например:
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 use here
ArgType<1, decltype(&f<double>)> //double - here it useless...
Ответ 2
Использовать шаблон?
template< typename T >
void f( T )
{
T a;
}
Ответ 3
Это зависит от того, что вы хотите сделать, где эта переменная будет использоваться. Если это функция, шаблон может быть хорошим выбором:
template<typename T>
void foo(T ) {
T a;
}
Альтернативно, если вы находитесь вне функции и имеете требование действительно знать это, вы можете использовать Boost.TypeTraits, то есть function_traits<void (int)>::arg1_type
даст int
Ответ 4
Один из подходов - использовать typedef для типа параметра функции. Например
typedef int TParm;
void f( TParm );
TParm a;
Вы можете выбрать любое имя для этого типа. Например parm_t
и т.д. Важно, чтобы не было столкновения имен.
В этом случае вам нужно будет изменить только typedef, если вы хотите изменить тип параметра.
Или, если ваш компилятор поддерживает псевдонимы, вы также можете написать
using TParm = int;
void f( TParm );
TParm a;
Также вы можете обернуть функцию в пространстве имен или классе.:) Например
struct IFunction
{
typedef int parm_t;
static void f( parm_t = parm_t() ) {}
};
//...
IFunction::parm_t a;
IFunction::f( a );
Ответ 5
Как создать функцию шаблона?
template <typename T>
void f(T t);