使用模板参数获取函数的参数类型
Getting the argument type of a function with template argument
我有一个有效的代码,除了以下行
std::is_same<first_argument<functorArgTemplated>::type,int>::value <<std::endl; // this does not work
有人知道我必须添加什么样的 helper() 定义吗?
编译错误为
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): error C2065: 'functorArgTemplated': undeclared identifier
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): error C2923: 'first_argument': 'functorArgTemplated' is not a valid template type argument for parameter 'F'
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): error C2955: 'first_argument': use of class template requires template argument list
1> d:\git\testprojekt\testprojekt\testprojekt.cpp(22): note: see declaration of 'first_argument'
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): warning C4552: '<<': operator has no effect; expected operator with side-effect
完整代码:
#include <iostream>
template<typename F, typename Ret>
void helper(Ret(F::*)());
template<typename F, typename Ret>
void helper(Ret(F::*)() const);
template<typename F, typename Ret, typename A, typename... Rest>
void helper(Ret(F::*)(A, Rest...));
template<typename F, typename Ret, typename A, typename... Rest>
void helper(Ret(F::*)(A, Rest...) const);
template<typename F, typename Ret, typename A, typename... Rest>
void helper(Ret(F::*)(A, Rest...) const);
template<typename F>
struct first_argument {
typedef decltype(helper(&F::operator())) type;
};
template <typename Functor, typename Arg = typename first_argument<Functor>::type>
struct DoStuff;
template <typename Functor>
struct DoStuff<Functor, char>
{
void print() { std::cout << "has arg" << std::endl; };
};
template <typename Functor>
struct DoStuff<Functor, void>
{
void print() { std::cout << "does not have arg" << std::endl; };
};
struct functorNoArg {
void operator() () {};
};
struct functorArg {
void operator()(int a) { std::cout << a; };
};
struct functorArgTemplated {
template <typename TArg>
int operator()(TArg a) { std::cout << a; return a; };
};
int main()
{
auto lambdaNoArg = []() {};
auto lambdaArg = [](int a) {};
std::cout << std::is_same<first_argument<functorArgTemplated>::type,int>::value <<std::endl; // this does not work
DoStuff<functorArg> doStuff;
doStuff.print();
DoStuff<functorNoArg> doStuff2;
doStuff2.print();
DoStuff<decltype(lambdaArg)> doStuff3;
doStuff3.print();
DoStuff<decltype(lambdaNoArg)> doStuff4;
doStuff4.print();
return 0;
}
在 C++ 中,您可以回答问题 "can I invoke this with an int
" 并获得答案(在直接上下文中),但您不能回答 "what can I invoke this with"。
在一般情况下,回答第二个问题需要解决 Halt,因为在 C++ 中使对象可接受的参数可以是图灵完备计算。
你解决了简单情况下的问题:一般问题无法解决。在最简单的情况下解决它需要越来越多的黑客以各种方式得到错误的答案。
通常试图回答这个问题是问错问题或在编写 scripting/language 接口代码时想要 DRY 的混合体(通常使用元编程或类型系统不那么荒谬的语言,或者缩小传输的类型信息)。在 SO 上问这个问题的人倾向于询问他们的狭隘问题,而懒得提及是什么导致他们走上了这条死胡同:post a MCVE and[=22= 总是一个好主意] 问题背后的动机草图。
我有一个有效的代码,除了以下行
std::is_same<first_argument<functorArgTemplated>::type,int>::value <<std::endl; // this does not work
有人知道我必须添加什么样的 helper() 定义吗?
编译错误为
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): error C2065: 'functorArgTemplated': undeclared identifier
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): error C2923: 'first_argument': 'functorArgTemplated' is not a valid template type argument for parameter 'F'
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): error C2955: 'first_argument': use of class template requires template argument list
1> d:\git\testprojekt\testprojekt\testprojekt.cpp(22): note: see declaration of 'first_argument'
1>d:\git\testprojekt\testprojekt\testprojekt.cpp(60): warning C4552: '<<': operator has no effect; expected operator with side-effect
完整代码:
#include <iostream>
template<typename F, typename Ret>
void helper(Ret(F::*)());
template<typename F, typename Ret>
void helper(Ret(F::*)() const);
template<typename F, typename Ret, typename A, typename... Rest>
void helper(Ret(F::*)(A, Rest...));
template<typename F, typename Ret, typename A, typename... Rest>
void helper(Ret(F::*)(A, Rest...) const);
template<typename F, typename Ret, typename A, typename... Rest>
void helper(Ret(F::*)(A, Rest...) const);
template<typename F>
struct first_argument {
typedef decltype(helper(&F::operator())) type;
};
template <typename Functor, typename Arg = typename first_argument<Functor>::type>
struct DoStuff;
template <typename Functor>
struct DoStuff<Functor, char>
{
void print() { std::cout << "has arg" << std::endl; };
};
template <typename Functor>
struct DoStuff<Functor, void>
{
void print() { std::cout << "does not have arg" << std::endl; };
};
struct functorNoArg {
void operator() () {};
};
struct functorArg {
void operator()(int a) { std::cout << a; };
};
struct functorArgTemplated {
template <typename TArg>
int operator()(TArg a) { std::cout << a; return a; };
};
int main()
{
auto lambdaNoArg = []() {};
auto lambdaArg = [](int a) {};
std::cout << std::is_same<first_argument<functorArgTemplated>::type,int>::value <<std::endl; // this does not work
DoStuff<functorArg> doStuff;
doStuff.print();
DoStuff<functorNoArg> doStuff2;
doStuff2.print();
DoStuff<decltype(lambdaArg)> doStuff3;
doStuff3.print();
DoStuff<decltype(lambdaNoArg)> doStuff4;
doStuff4.print();
return 0;
}
在 C++ 中,您可以回答问题 "can I invoke this with an int
" 并获得答案(在直接上下文中),但您不能回答 "what can I invoke this with"。
在一般情况下,回答第二个问题需要解决 Halt,因为在 C++ 中使对象可接受的参数可以是图灵完备计算。
你解决了简单情况下的问题:一般问题无法解决。在最简单的情况下解决它需要越来越多的黑客以各种方式得到错误的答案。
通常试图回答这个问题是问错问题或在编写 scripting/language 接口代码时想要 DRY 的混合体(通常使用元编程或类型系统不那么荒谬的语言,或者缩小传输的类型信息)。在 SO 上问这个问题的人倾向于询问他们的狭隘问题,而懒得提及是什么导致他们走上了这条死胡同:post a MCVE and[=22= 总是一个好主意] 问题背后的动机草图。