template instantiation with constexpr function failure

最后都变了- 提交于 2019-11-29 01:22:02

It looks like this restriction was subject to the following proposal Allow constant evaluation for all non-type template arguments, still trying to determine the status of this proposal. It says:

The syntactic restrictions for pointers, references, and pointers to members are awkward and prevent reasonable refactorings. For instance:

template<int *p> struct A {};
int n;
A<&n> a; // ok

constexpr int *p() { return &n; }
A<p()> b; // error

and further says:

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. The status quo is that an implementation is required to evaluate such a template argument, but must then discard the result if it turns out to not be null.

In addition to the above, the restriction to entities with linkage is an artifact of exported templates, and could have been removed when the linkage restrictions on template type parameters were removed.

and it would remove this section of the note with this restriction:

unnamed lvalues, and named lvalues with no linkage

the whole note reads:

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

Update

The revised version of this proposal N4268 was adopted into the working draft at Urbana and we can see the changes in the latest working draft N4296. The new note reads:

A temporary object is not an acceptable template-argument when the corresponding template-parameter has reference type

The normative section is 14.3.2 (temp.arg.nontype) paragraph 1 which with this proposal would say:

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.14.5),
  • the result of a typeid expression (5.2.8), or
  • a predefined func variable (8.4.1).

and we can find this new wording in the latest draft standard N4296.

It looks like this change has actually been implemented in clang HEAD see your code working live, using the -std=c++1z flag. This implies the change should be part of C++17, assuming no subsequent changes reverses or alters it.

In the case of

C<h()> oo;

§14.3.2/4 kicks in:

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

(emphasis mine)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!