Vit*_*meo 8 c++ templates language-lawyer constexpr c++17
请考虑以下代码:
template <int N, typename T> void f(T) { }
template <typename T>
constexpr int k(T&) { return 0; }
int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}
Run Code Online (Sandbox Code Playgroud)
clang++ (主干)编译它.g++ (trunk)因以下错误而失败:
Run Code Online (Sandbox Code Playgroud)<source>: In lambda function: <source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)' 11 | f<k(i)>(0); | ^ <source>:1:35: note: candidate: 'template<int N, class T> void f(T)' 1 | template <int N, typename T> void f(T) { } | ^ <source>:1:35: note: template argument deduction/substitution failed: <source>:11:19: error: '__closure' is not a constant expression 11 | f<k(i)>(0); | ^ <source>:11:13: note: in template argument for type 'int' 11 | f<k(i)>(0); | ~^~~
改变k(T&)以k(T)解决问题.在我看来,问题与引用参数不是常量表达式但不用作其一部分的事实有关k.
这里的编译器是正确的?
GCC在这里是正确的.
表达式
e是核心常量表达式,除非按照e抽象机器的规则评估以下表达式之一:
- ...
- 在lambda表达式中,对一个变量的引用,该变量具有在lambda表达式之外定义的自动存储持续时间,其中引用将是odr-use; ...
- ...
k(i)i因此,odr-uses k(i)不是lambda表达式中的常量表达式,因此该代码是不正确的.