2015-05-06 80 views
3
#include <utility> 

struct A { 
    constexpr auto one(int a) { 
     return std::integral_constant<int, _data[a]>{}; 
    } 
    constexpr int two(int a) const { 
     return _data[a]; 
    } 

    int _data[10]; 
}; 

int main() { 
    constexpr auto ex = A{{1,2,3,4,5,6,7,8,9,10}}; 

    std::integral_constant<int, ex.two(3)> b{}; 
} 

上面的代碼不會在主幹鐺中編譯。該錯誤是在one()成員函數,並說:C++ constexpr自動成員函數。鏗鏘的問題?

cc.cpp:57:44: note: implicit use of 'this' pointer is only allowed 
    within the evaluation of a call to a 'constexpr' member function. 

顯然,函數標記爲constexpr,如果你註釋掉one()成員,一切編譯罰款,所以我們顯然能夠從創建integral_constantex,但不是直接從struct?這似乎是,當我需要auto返回類型扣除,它失敗並聲稱該功能不是constexpr

這是預期嗎?我覺得這不應該是一個問題,如果這是預期的行爲,我會感到驚訝。

+2

'_data [a]'不是'A :: one'內的常量表達式。請注意,'constexpr'函數仍然可以在運行時調用,例如如果您提供僅在運行時已知的參數。 – dyp

+0

這是'two'中的一個constexpr,通過使用它的返回值作爲模板參數來證明它? – pat

+2

據我所知,'_data [a]'在兩個成員函數中都不是一個常量表達式。但是constexpr函數可以由非常量表達式組成。規則是:在需要一個常量表達式的上下文中,不可以評估非常量的東西(包括一個constexpr函數的一部分)。另外,在需要常量表達式的上下文中,必須有一種方法可以合法調用'constexpr'函數。 – dyp

回答

6

如果考慮[dcl.constexpr]/7這樣的說法:

constexpr函數調用產生相同的結果作爲呼叫爲等效的非constexpr功能在各方面除了可以在常量表達式中出現對constexpr函數的調用。

考慮非等效函數A::one()_data[a]不能在常量表達式中使用(作爲非類型模板參數),因爲它會涉及的this評價中,從[expr.const]:

甲條件表達式e是一個核心常量表達式除非按照 抽象機(1.9)的規則對e的評估將評估以下表達式之一:
(2.1) - this(5.1。1),除了constexpr函數或constexpr構造函數被評估爲 的一部分;

由於非constexpr相當於不合格,所以constexpr函數給出相同的結果是合理的。

安大略省另一方面,two()是一個結構良好的成員函數,無論constexpr和你的ex.two(3)用途是作爲一個常量表達式有效 - 這就是爲什麼它編譯。

+0

宏偉的答案。你能引用一段標準,告訴爲什麼'two'在常量表達式中工作嗎?在'constexpr'對象上調用方法時''this'獲得'constexpr'限定的部分是由我以實驗方式確定的。 –

+0

@ polkovnikov.ph該標準提供了一些可以防止表達式成爲常量表達式的內容列表 - 只是它們都不適用。除了'constexpr',[]調用函數,而不是'constexpr'函數,[]調用未定義的函數,[] UB,[] lambda,[x]左值到右值的轉換但[x] **除非**指的是用'constexpr'定義的對象的不可變子對象,... – Barry

1
  1. constexpr功能是爲了使它們可以在編譯時和運行時被調用。
  2. 如果您可以省略constexpr並獲得正確的普通函數,則具有constexpr函數的代碼格式良好。換句話說,它必須編譯爲運行時功能
  3. 如果constexpr函數的主體不能在編譯時計算,它仍然被編譯,但不能在編譯時上下文中使用它,例如模板參數。
  4. 如果constexpr方法在constexpr對象上調用,this被視爲constexpr。

one情況下,它是形成不良的,因爲當它編譯成在運行時運行,_data[a]被認爲是一個運行時的表現,因爲a不是一個常量表達式,即使thisthis->_data是。

two情況下,它編譯罰款,因爲它工作正常運行時,在編譯時thisconstexpr儘可能a,使this->_data[a]constexpr,一切工作正常。

+0

刪除'one'函數編譯好,編譯時環境中使用'two'? – pat

+0

從字面上看,在這個例子中,我使用兩個作爲模板參數的調用。 – pat