代码之家  ›  专栏  ›  技术社区  ›  João Paulo

deafult型变量模板

  •  0
  • João Paulo  · 技术社区  · 7 年前

    我正在尝试创建一个默认指针类型的参数包:

    template<int*... T>
    void f() {}
    

    我发现这个代码有错误:

    int main(){
        int* a = new int(5);
        f<a>();
    }
    

    int main(){
        f<nullptr>();
    }
    

    为什么?

    错误:

    ./example.cpp: In function 'int main()': ./example.cpp:6:7: error: the
    value of 'a' is not usable in a constant expression
         f<a>();
           ^ ./example.cpp:5:10: note: 'a' was not declared 'constexpr'
         int* a = new int;
              ^ ./example.cpp:6:10: error: no matching function for call to 'f<a>()'
         f<a>();
              ^ ./example.cpp:2:6: note: candidate: 'template<int* ...T> void f()'  void f() {}
          ^ ./example.cpp:2:6: note:   template argument deduction/substitution failed: ./example.cpp:6:10: error: 'a' is not a
    valid template argument because 'a' is a variable, not the address of
    a variable
         f<a>();
              ^ Compiler returned: 1
    

    Compiler Explorer

    0 回复  |  直到 7 年前
        1
  •  3
  •   SergeyA    7 年前

    非类型模板参数的参数必须为 constant expression .

    int* a = new int(5);
    

    在这个片段中, a 不是常量表达式,不适用于模板非类型参数。

    事实上,这在直觉上应该是可以接受的。请记住,在执行程序之前,编译器需要为实例化的模板生成代码,并且该代码必须使用模板参数的值。但是 A. 在编译时是未知的——它可以是任何东西,这取决于内存分配的位置。显然,编译器无法预测它的值。

    另一方面,全局(或函数静态)对象的地址可以用作非类型指针模板参数:

    int k = 10;
    
    int main(){
        f<&k>();
    }
    

    上面的代码可以工作,这在直觉上是有意义的,因为编译器会知道全局对象的位置(编译器会自己把它放在那里!)

    最后,但并非最不重要的是,你的头衔是不必要的。这些规则同样适用于非变量模板。