在运行时,是否有任何方法可以确定C ++ 03中方法参数的类型?我正在考虑这样的方式:
#include <cstdio>
template<class T, class U>
struct is_same {
static const bool result = false;
};
template<class T>
struct is_same<T, T> {
static const bool result = true;
};
template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(ToFind, Ret (T::*)(Arg)){return is_same<ToFind, Arg>::result;}
template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(ToFind, Ret (T::*)(Arg1, Arg2)){return is_same<ToFind, Arg1>::result;}
struct A
{
int fun1(int a){return a+1;}
};
int main() {
std::printf("int arg1: %s\n", hasArg1(1, &A::fun1) ? "yes" : "no");
}
但是我想要这样的东西:
hasArg1<int>(&A::fun1)
代替
hasArg1(1, &A::fun1)
答案 0 :(得分:4)
只需删除第一个函数参数:
template<class ToFind, class Ret, class T, class Arg>
bool hasArg1(Ret (T::*)(Arg)){return is_same<ToFind, Arg>::result;}
template<class ToFind, class Ret, class T, class Arg1, class Arg2>
bool hasArg1(Ret (T::*)(Arg1, Arg2)){return is_same<ToFind, Arg1>::result;}
现在hasArg1<int>(&A::fun1)
可以按您的意愿工作。
但是请记住,如果A::fun1
重载,则此方法将无效。
现在,正如您在问题中所指出的。在运行时检查这些东西的用处不大。通常,您希望这些信息在编译时影响代码生成并可能基于此进行优化。与以后的版本相比,c++03的编译时功能受到限制,但是在编译时进行此检查并非并非不可能。这是修改代码的方法:
template<bool C, typename T = void>
struct enable_if;
template<typename T>
struct enable_if<true, T> { typedef T type; };
template<int s> struct tag { char _[s]; };
template<class ToFind>
tag<1> hasArg1(...);
template<class ToFind, class Ret, class T, class Arg>
tag<2> hasArg1(Ret (T::*)(Arg), enable_if<is_same<ToFind, Arg>::result, void>* = 0);
// Add hasArg1 overloads to support members with more arguments
#define HAS_ARG1(ToFind, member) (sizeof(hasArg1<ToFind>(member)) != sizeof(tag<1>))
首先,我们添加一个“后备”重载,该重载返回具有预期大小的类型。然后,我们添加另一个重载,由您自己修改。该检查被移交给另一个函数参数。如果在重载解析期间检查失败,则参数格式错误,替换失败,仅留下后备功能,因为SFINAE很棒!
如果检查通过,则第二个重载格式正确且匹配性更好,因为在重载分辨率中,省略号在转换序列中的优先级最低。
为语法糖添加了宏,因为随后的细节要反复键入很繁琐。我们在sizeof
运算符中进行重载解析。通过其返回类型选择的重载将反映在sizeof(hasArg1<ToFind>(member))
报告中。因此,我们可以对照sizeof(tag<1>)
(后备)进行检查。而且由于sizeof
是一个编译时间运算符,所以我们有一个编译时间常数,它告诉我们member
的第一个参数是否为ToFind
。
为了证明它是一个编译时间常数,我们可以实例化
tag<HAS_ARG1(int, &A::fun1)> test_compile_time;
就像我们做的here, in GCC 4.1.2 in C++98 mode一样。