为什么术语不能评估一个带0个参数的函数?

时间:2012-01-06 02:14:18

标签: c++ visual-c++ visual-c++-2008

当我尝试编译

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参数调用...所以为什么不编译?

3 个答案:

答案 0 :(得分: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 ++编译器中的限制。

答案 1 :(得分: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?

答案 2 :(得分: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;
}

生成(使用g ++(Ubuntu / Linaro 4.7.3-1ubuntu1)4.7.3)

void: no
void (*)(void): no
void (*)(int): no
int (*)(void): yes
int (*)(int): no