2016-07-15 93 views
6

以下代碼使用枚舉成員m作爲常量表達式,即作爲模板參數。代碼在gcc下編譯,但不在clang下(live demo)。鏗鏘說:「錯誤:非類型模板參數不是一個常量表達式」。使用枚舉作爲常量表達式。哪個編譯器是正確的?

該問題可以通過A<tst<p>::m> a交換// 1來解決。因此,我的問題不是如何解決這個問題,而是哪個編譯器是正確的。

template<size_t n> struct A{}; 

template<size_t n> 
struct tst 
{ enum : size_t { m= n % 15 }; 

    template<size_t p> 
    void 
    call(tst<p> const &t2) { 
     A<t2.m> a; // 1 
    } 
}; 
+0

[This references says](http://en.cppreference.com/w/cpp/language/enum)「當非範型枚舉是類成員時,它的枚舉器可以使用類成員訪問運算符'.'來訪問。和' - >'「。它沒有提到任何關於常量表達的內容。 –

+1

@JoachimPileborg標準的§7.2.2'確實說' 枚舉器列表中的標識符被聲明爲常量,並且可以出現在需要常量的地方。' – lcs

回答

3

根據該標準,Clang有權拒絕該代碼。

t2.m是一個類成員訪問表達式。 [expr.ref]/1說:

[...] The postfix expression before the dot or arrow is evaluated; the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.

還有一張紙條:

If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.

所以,子表達式t2進行評估。 [expr.const] /2.9說,表達e不能是核心常量表達式如果計算它在

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

  • it is initialized with a constant expression or
  • its lifetime began within the evaluation of e ;

t2的評價結果​​是指參考類型的變量不滿足子彈,所以t2.m不是一個常量表達式,因爲它不是一個核心常量表達式。


來自N4594的所有報價是當前發佈的工作草案。自C++ 11以來,文本發生了輕微的變化,但這種情況下的含義是相同的。

+0

Thx。有沒有人提交gcc的錯誤報告? –

+0

@ClaasBontus我沒有。通過錯誤數據庫的搜索將是有序的,但到目前爲止我還沒有時間做到這一點。 – bogdan

+0

可能[Bug 39970](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39970)。 –