当我尝试编译时
template<bool val>
struct boolean { static const bool value = val; };
template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> { }; // error!
int main(void) { bool b = is_callable<int (*)()>::value; }
我得到:
error C2064: term does not evaluate to a function taking 0 arguments
see reference to class template instantiation 'is_callable<T>' being compiled
我确信int (*)()
可以用0
参数调用。。。为什么不编译呢?
问题不在于int()
的使用。您可以从示例中完全删除它,并得到相同的错误。问题是当用作非类型模板参数时,sizeof
表达式本身。示例
template<bool val>
struct boolean { };
template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> // Error
{
void Test()
{
auto x = sizeof((*(T*)0)()) >= 0; // Compiles
}
};
希望另一个C++人员能来确定这个sizeof
表达式作为类型参数是否只是非法的,或者这只是MS C++编译器中的一个限制。
对我来说,这很有效。
typedef int (*X)();
template<typename T>
struct is_callable : boolean<sizeof((*(X*)(T*)0)()) >= 0> { }; // works!
因此,编译器似乎不确定在实例化模板类时是否总是将函数指针传递给T!。因此,强制编译器进行显式强制转换。
[编辑]:此外,经过进一步思考,我不明白你真正想做什么。你是想测量一个只接受一个参数的函数指针的大小吗?对于具有不同返回类型的函数,这会有什么不同?为什么常量表达式(sizeof(void*))需要模板?
请查看此线程以了解更多信息函数指针的大小有什么保证?
您可以使用简单的模板专门化。
#include <stdio.h>
template<typename T>
struct func_with_zero_args { static const bool value = false; };
template<>
struct func_with_zero_args <int (*)()> { static const bool value = true; };
#define STRINGIFY(t) "" #t
#define TEST(t) printf(STRINGIFY(t) ": %sn", (func_with_zero_args<t>::value ? "yes" : "no"));
int
main(int argc, const char* argv[])
{
TEST(void);
TEST(void (*)(void));
TEST(void (*)(int));
TEST(int (*)(void));
TEST(int (*)(int));
return 0;
}
生成(使用g++(Ubuntu/Linaro 4.7.3-1ubuntu1)4.7.3)
无效:否void(*)(void):否void(*)(int):否int(*)(void):是int(*)(int):否