c++ - 具有默认类型的可变参数模板

标签 c++ c++11 templates variadic-templates

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

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

最佳答案

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

int* a = new int(5);

在此代码段中,a 不是常量表达式,不适用于模板非类型参数。

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

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

int k = 10;

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

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

最后但并非最不重要的一点是,您的标题不必要地狭窄。这些规则以相同的方式应用于非可变模板。

关于c++ - 具有默认类型的可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56193288/

相关文章:

c++ - 为什么必须在每个使用模板的函数之前声明模板?

c++ - 如何使用http请求只获取字符串名称

c++ - 在 C++ 的原始字符串中转义 R"()"

c++ - 自动模板实例化

c++ - 函数 vs lambda 作为函数参数

c++ - 在优先队列中随机访问

c++ - 使用先前 move 过的输出迭代器调用 move() 是标准 C++ 吗?

c++ - 对于单个参数,可变参数形式与非可变参数形式不明确

c++ - 如果使用 CRTP,如何在存在的情况下调用派生函数,否则使用默认值?

C++ 使用模板成员函数继承类