简体   繁体   English

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

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

Consider the simple C++11 code: 考虑一下简单的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
}

I can successfuly compile it with g++ -std=c++11 foo.cpp 我可以用g++ -std=c++11 foo.cpp成功编译它

however if I use clang++, clang++ -std=c++11 foo.cpp I get 但是,如果我使用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: compiler versions. I have checked the previous statement with g++ version 5.3.1 and 7.2.1 and with clang++ version 3.6.2 and 5.0.0) (nb:编译器版本。我用g ++版本5.3.1和7.2.1以及clang ++版本3.6.2和5.0.0检查了前一个语句)

My question: which of g++ or clang is right? 我的问题: g ++或clang中哪一个是对的? What is the problem? 问题是什么?

My interpretation is that clang++ is right and g++ is too permissive . 我的解释是clang ++是对的,g ++太宽容了

We can find a close example ([expr.const] section, page 126) in the standard https://isocpp.org/std/the-standard (draft can be downloaded, attention big PDF! ). 我们可以在标准https://isocpp.org/std/the-standard中找到一个接近的例子([expr.const]部分,第126页)(可以下载草稿, 注意大PDF! )。

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

    return x; 
}

where it is explained that: 在那里解释说:

error: incr(k) is not a core constant expression because lifetime of k began outside the expression incr(k) 错误:incr(k)不是核心常量表达式,因为k的生命周期开始于表达式incr(k)之外

This is exactly what is happening in the use_size() function with the foo argument, even if the size() function only use the N template parameter. 这正是带有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); }

I was expecting Clang to be wrong in this case. 在这种情况下,我期待Clang出错。 It should evaluate your function call as being a constant expression, simply because you use only the template parameter, and not the object itself. 它应该将您的函数调用评估为一个常量表达式,因为您只使用模板参数,而不是对象本身。 Since you don't use the object in your constexpr function, there should be nothing prohibit compile time evaluation. 由于您没有在constexpr函数中使用该对象,因此不应该禁止编译时评估。

However, there's a rule in the standard that says object that began their lifetime preceding the constant expression such as a reference is not useable as constexpr. 但是,标准中有一条规则,即在常量表达式(例如引用)之前开始其生命周期的对象不能用作constexpr。

There is a simple fix in that case. 在这种情况下有一个简单的解决方案。 I think it didn't like the reference: 我认为它不喜欢参考:

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

Here's a live example 这是一个实例

Alternatively, you can also copy your foo object and use that local object: 或者,您也可以复制您的foo对象并使用该本地对象:

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

Live example 实例

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

相关问题 g ++抱怨constexpr函数不是常量表达式 - g++ complains constexpr function is not a constant expression 使用 std::acos 和 clang++ 而不是 g++ 的 Constexpr 编译错误 - Constexpr compile error using std::acos with clang++ not g++ 类定义静态constexpr结构的未定义引用,g ++ vs clang - undefined reference to class static constexpr struct, g++ vs clang G ++ vs Clang:constexpr和const的行为不一致 - G++ vs Clang : inconsistent behavior for constexpr and const constexpr静态模板函数:g ++错误是对clang的警告 - constexpr static template function: g++ error is a warning on clang clang++ vs g++ constexpr 与越界引用的区别 - clang++ vs g++ constexpr difference with out of bound reference C ++ 11构造函数重载解析和Initialiser_lists:clang ++和g ++意见不同 - C++11 constructor overload resolution and initialiser_lists: clang++ and g++ disagree 在类中定义的友元函数模板是否可用于查找? clang ++和g ++不同意 - Is a friend function template defined in the class available for lookup? clang++ and g++ disagree gcc和clang对constexpr功能不一致 - gcc and clang disagree over constexpr function Clang,LLVM和g ++ - Clang, LLVM, and g++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM