c++ - 非类型引用参数/参数

标签 c++ templates c++11 reference non-type

为什么非类型引用的模板参数不能是另一个引用(g++ 4.8.1):

template <int& N> void test() { }

int x = 5;
int& p = x;

int main(){
    test<x>(); //compiles fine
    test<p>(); //error: could not convert template argument 'p' to 'int&'|  
}

我看不到标准 p 哪里违反了任何内容,这些似乎是最相关的部分 (N3337):

[14.3.2] [.1] A template-argument for a non-type, non-template template-parameter shall be one of:

— for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or

— the name of a non-type template-parameter; or

— a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or .....

[.4]

[ Note: Temporaries, unnamed lvalues, and named lvalues with no linkage are not acceptable templatearguments when the corresponding template-parameter has reference type.

[.5]

— For a non-type template-parameter of type reference to object, no conversions apply. The type referred to by the reference may be more cv-qualified than the (otherwise identical) type of the templateargument. The template-parameter is bound directly to the template-argument, which shall be an lvalue.

p 应该被认为是一个左值,不是吗?我唯一能想到的另一件事是可能缺少引用链接,但添加 extern int& p = x 也没有解决它。

最佳答案

这与之前的问题template instantiation with constexpr function failure有关我刚才在评论中链接了它,尽管你的情况不同。

看起来该示例以前是不允许的,但通过提案 Allow constant evaluation for all non-type template arguments 将支持添加到 C++1z 中打开:

the syntactic restrictions for pointers, references, and pointers to members are awkward and prevent reasonable refactorings. [...] The historical reason for the restriction was most likely that C++ previously did not have a sufficiently strong specification for constant expressions of pointer, reference, or pointer-to-member type. However, that is no longer the case. [...]

似乎与您的案例相关的具体更改是 C++ 标准部分草案 14.3.2 模板非类型参数 [temp.arg.nontype]/p1 的改写来自:

A template-argument for a non-type, non-template template-parameter shall be one of:

[...]

  • a constant expression (5.19) that designates the address of a complete object with static storage durationtion and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or

[...]

到:

A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • a subobject (1.8),

  • a temporary object (12.2),

  • a string literal (2.13.5),

  • the result of a typeid expression (5.2.8), or

  • a predefined func variable (8.4.1).

5.20 Constant expressions [expr.const]/p4 部分有以下关于转换后的常量表达式的段落,开头是:

A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only

特别添加了这个:

[...] and where the reference binding (if any) binds directly [...]

请注意,当前的 clang head 版本以 C++1z 模式编译您的代码,see it live .

N4268 的更新版本是应用的那个clang C++1z implementation status section表示这篇论文得到了 clang 3.6 的支持。此代码仅适用于 clang 3.6 及更高版本的 C++1z 模式。

关于c++ - 非类型引用参数/参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33301552/

相关文章:

c++ - 在 Firebreath 中更改 Makefile

templates - 向 EEx 模板公开函数

c++ - 使用 std::enable_if 保护复制构造函数

c++ - GCC 8 无法编译 make_shared<volatile int>()

c++ - C++中的继承语法

c++ - 为什么 OpenGL 方法不返回任何内容?

c++ - Intel Inspector 报告我的自旋锁实现中存在数据竞争

c++ - "template<class C> void mini(C &a4, C b4) { a4 = min(a4, b4); }"定义是什么意思?

c++ - 模板类比使用相同类型的非模板类大吗?

c++ - 标准布局类型和 reinterpret_cast