【问题标题】:Why is term not evaluating to a function taking 0 arguments?为什么 term 不评估带 0 个参数的函数?
【发布时间】:2012-02-03 20:59:35
【问题描述】:

当我尝试编译时

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

【问题讨论】:

  • @KerrekSB:嗯,这很有趣......我在 VC 2010 上尝试过,它也给出了错误。那么它是一个错误吗?我不知道,因为有一个空指针被取消引用,但实际上我看不出它有什么问题......
  • 没有取消引用。 sizeof 不评估它的论点。

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


【解决方案1】:

问题不在于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++ 编译器中的一个限制。

【讨论】:

  • 这里没有“类型”参数。 val 是一个非类型参数。
  • @KerrekSB doh。更正为“模板参数”。
  • 它仍然是一个非类型模板参数。
  • val 是一个值模板参数。 sizeof 的结果是一个值。这似乎不是问题。
  • @SionSheevok Nitpick:没有值模板参数这样的东西。参数只有 3 种类型:类型、非类型和模板。 (14.3)
【解决方案2】:

对我来说这是可行的。

    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?

【讨论】:

    【解决方案3】:

    您可以只使用简单的模板特化。

    #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)

    无效:没有 无效(*)(无效):无 无效(*)(int):没有 int (*)(void): 是 整数(*)(整数):没有

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      • 2019-05-24
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      相关资源
      最近更新 更多