簡體   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