作为非类型模板参数引用
Reference as a non-type template argument
下面的示例尝试使用引用类型的变量作为非类型模板参数(本身为引用类型(的参数。Clang,GCC和VC++都拒绝它。但是为什么?我似乎在标准中找不到任何使其非法的东西。
int obj = 42;
int& ref = obj;
template <int& param> class X {};
int main()
{
X<obj> x1; // OK
X<ref> x2; // error
}
现场示例
咕噜 说:
source_file.cpp:9:7: 错误:引用类型为"int &"的非类型模板参数不是对象
其他人则以类似的方式抱怨。
来自
标准(所有报价来自 C++11;C++14 在相关部分似乎没有重大变化(:
14.3.2/1 非类型、非模板模板参数的模板参数应为以下参数之一:
。
- 一个常量表达式 (5.19(,用于指定具有静态存储持续时间和外部或内部链接的对象地址......表示(忽略括号(作为
&
id 表达式,除了&
...如果相应的模板参数是引用,则应省略。
现在什么是常量表达式:
5.19/2 条件表达式是核心常量表达式,除非它涉及以下作为潜在评估的子表达式之一 (3.2(...
。
引用
- 引用类型的变量或数据成员的 ID 表达式,除非引用具有前面的初始化,使用常量表达式初始化
。
据我所知,X<ref>
中的ref
是一个 id 表达式,它引用了引用类型的变量。此变量具有前面的初始化,使用表达式 obj
进行初始化。我相信obj
是一个常量表达式,无论如何,如果不是,那么X<obj>
也不应该编译。
- 那么我错过了什么?
- 标准中的哪个条款使
X<ref>
无效,而X<obj>
是有效的?
简介
不过,引用的名称是id表达式是正确的;id表达式不引用引用的任何内容,而是引用引用本身。
int a = 0;
int& ref = a; // "ref" is an id-expression, referring to `ref` - not `a`
<小时 />标准 (N4140(
您在帖子中引用了标准的相关部分,但您遗漏了最重要的部分(强调我的(:
14.3.2p1 模板非类型参数 [temp.arg.nontype]
非类型、非模板模板参数的模板参数应为以下参数之一:
。
一个常量表达式 (5.19(,它指定具有静态动态持续时间和外部或内部链接的完整对象的地址,或具有外部或内部链接的函数,包括函数模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号(
&
id-表达式,其中 id-expression 是对象或函数的名称,但如果名称引用函数或数组,则可以省略&
,如果相应的模板参数是引用,则应省略;。
注意:在早期的草案中,"其中id-expression是对象或函数的名称">不存在;DR 1570解决了这个问题 - 这无疑使意图更加清晰。
<小时 />引用类型的变量不是对象?
你是绝对正确的;引用本身具有引用类型,并且当表达式的一部分时只能充当对象。
<小时 />5p5 表达式 [expr]
如果表达式最初具有"引用
T
"(8.3.2,8.5.3(的类型,则在进行任何进一步分析之前,该类型将调整为T
。表达式指定由引用表示的对象或函数,表达式是左值或 x值,具体取决于表达式。
阐述
非常重要的是要注意常量表达式("指定一个完整对象的地址......">( 必须是 &id-expression
或 id-expression
之一。
即使常量表达式(不仅仅是 id 表达式(可能引用具有静态存储持续时间的对象,我们也不能使用它来"初始化">引用或指针类型的模板参数。
示例代码段
template<int&>
struct A { };
int a = 0;
constexpr int& b = (0, a); // ok, constant-expression
A<(0, a)> c = {}; // ill-formed, `(0, a)` is not an id-expression
注意:这也是我们不能使用字符串文字作为模板参数的原因;它们不是id表达式。
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 通过常量引用传递参数的矩阵模板类
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 何时应通过引用传递矢量参数而不是按值传递矢量参数?
- 具有常量引用参数的函数模板专用化
- 作为参数引用
- 在 cpp 文件中隐藏采用模板参数引用的方法
- 如何传递带有通过引用传递的结构参数的函数?
- 将输入参数作为右值引用传递?
- 使用引用与指针将数组作为参数传递
- 根据模板参数引用不同基类的函数
- 默认情况下C++数组作为参数引用
- 对指针C++的参数引用
- 作为非类型模板参数引用
- 重用返回语句或按参数引用返回
- 将参数引用传递给函数C++
- 从另一个参数引用的模板可变参数
- 成员变量多态性和参数引用
- 按参数引用或按参数引用之间的差异
- 无法实例化抽象类:为什么模板参数(引用)导致这种情况