繁体   English   中英

constexpr表达式和变量生命周期,g ++和clang不同意的例子

[英]constexpr expression and variable lifetime, an example where g++ and clang disagree

考虑一下简单的C ++ 11代码:

template<int N>
struct Foo {};

template <int N>
constexpr int size(const Foo<N>&) { return N; }

template <int N>
void use_size(const Foo<N>& foo) { constexpr int n = size(foo); }

int main()
{
    Foo<5> foo;

    constexpr int x = size(foo);  // works with gcc and clang
                                  // _but_
    use_size(foo);                // the same statement in the use_size() 
                                  // function _only_ works for gcc
}

我可以用g++ -std=c++11 foo.cpp成功编译它

但是,如果我使用clang ++, clang++ -std=c++11 foo.cpp我得到了

foo.cpp:15:28: error: constexpr variable 'n' must be initialized by a constant expression
void use_size(const Foo<N>& foo) { constexpr int n = size(foo); }
                                                     ~~~~~^~~~
foo.cpp:23:5: note: in instantiation of function template specialization 'use_size<5>' requested here
    use_size(foo);                // the same statement in the use_size() 
    ^
1 error generated.

(nb:编译器版本。我用g ++版本5.3.1和7.2.1以及clang ++版本3.6.2和5.0.0检查了前一个语句)

我的问题: g ++或clang中哪一个是对的? 问题是什么?

我的解释是clang ++是对的,g ++太宽容了

我们可以在标准https://isocpp.org/std/the-standard中找到一个接近的例子([expr.const]部分,第126页)(可以下载草稿, 注意大PDF! )。

constexpr int g(int k) { 
    constexpr int x = incr(k); 

    return x; 
}

在那里解释说:

错误:incr(k)不是核心常量表达式,因为k的生命周期开始于表达式incr(k)之外

这正是带有foo参数的use_size()函数中发生的情况,即使size()函数使用N模板参数。

template <int N>
constexpr int size(const Foo<N>&) { return N; }

template <int N>
void use_size(const Foo<N>& foo) { constexpr int n = size(foo); }

在这种情况下,我期待Clang出错。 它应该将您的函数调用评估为一个常量表达式,因为您只使用模板参数,而不是对象本身。 由于您没有在constexpr函数中使用该对象,因此不应该禁止编译时评估。

但是,标准中有一条规则,即在常量表达式(例如引用)之前开始其生命周期的对象不能用作constexpr。

在这种情况下有一个简单的解决方案。 我认为它不喜欢参考:

template <int N> // pass by value, clang is happy
void use_size(Foo<N> foo) { constexpr int n = size(foo); }

这是一个实例

或者,您也可以复制您的foo对象并使用该本地对象:

template <int N>
void use_size(const Foo<N>& foo) {
    auto f = foo;
    constexpr int n = size(f);
}

实例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM