2012-01-06 34 views
4

当我尝试编译为什么术语不评估一个带有0个参数的函数?

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参数...那么,为什么不这样编?

+2

工程在GCC 4.6.2。 – 2012-01-06 02:19:39

+0

@KerrekSB:呵呵,这很有趣...我用VC 2010试了一下,它也给出了一个错误。那么它是一个错误?我不知道,因为有一个空指针被解除引用,但实际上我没有看到它的任何错误... – Mehrdad 2012-01-06 02:22:48

+5

没有取消引用。 'sizeof'不会评估它的参数。 – 2012-01-06 02:24:30

回答

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++编译器的限制。

+3

这里没有“type”参数。 'val'是一个*非类型*参数。 – 2012-01-06 02:25:35

+0

@KerrekSB doh。更正说“模板参数”。 – JaredPar 2012-01-06 02:26:32

+0

它仍然是*非类型*模板参数。 – 2012-01-06 02:27:04

0

对我来说这个工程。

typedef int (*X)(); 

    template<typename T> 
    struct is_callable : boolean<sizeof((*(X*)(T*)0)()) >= 0> { };   // works! 

因此,看起来编译器并不确定在实例化模板类时,您总是会传递一个指向T的函数指针!所以,强制编译器进行明确的转换。

[编辑]:另外,在进一步思考时,我不明白你真的想要做什么。你想测量一个函数指针的大小,它只需要一个参数?对于具有不同返回类型的函数,这将如何变化?为什么你需要模板来获得一个常量表达式(sizeof(void *))?

请检查该线程更多的理解 What is guaranteed about the size of a function pointer?

0

你可以只使用简单的模板专业化。

#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) ": %s\n", (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; 
} 

生成(采用克++(Ubuntu的/ Linaro的4.7.3-1ubuntu1)4.7.3)

 
void: no 
void (*)(void): no 
void (*)(int): no 
int (*)(void): yes 
int (*)(int): no 
相关问题