2015-09-27 56 views
5

請考慮以下兩個C++ 14的方案:constexpr成員函數不使用這個?

計劃1:

struct S { constexpr int f() const { return 42; } }; 
S s; 
int main() { constexpr int x = s.f(); return x; } 

方案2:

struct S { constexpr int f() const { return 42; } }; 
int g(S s) { constexpr int x = s.f(); return x; } 
int main() { S s; return g(s); } 

既不是,一個或兩個這些程序的不良形成的?

爲什麼/爲什麼不呢?

回答

2

這兩個程序都格式良好。 C++ 14標準要求是一個常量表達式,因爲它被用來初始化一個constexpr變量,事實上它是一個核心常量表達式,因爲沒有理由不這樣做。表達式可能不是核心常量表達式的原因列在5.19 p2節中。尤其是,它聲明表達式的評估將不得不做幾件事之一,其中沒有一件是在你的例子中完成的。

這可能會令人驚訝,因爲在某些情況下,將非常量表達式傳遞給constexpr函數可能會導致結果爲非常量表達式,即使未使用該參數也是如此。例如:

constexpr int f(int) { return 42; } 

int main() 
{ 
    int x = 5; 
    constexpr y = f(x); // ill-formed 
} 

然而,這是形成不良的原因是因爲左值到右值轉換非恆定表達的,這是的事情之一是,表達的評價是不允許的。在調用的情況下不會發生左值到右值的轉換。

-3

這聽起來像一個測驗的問題,而不是由學生提出,但教授的計算器測試公衆開放,但讓我們來看看......

讓我們先從一個定義規則。很明顯,兩個版本都沒有違反這個規定,所以他們都通過了這個部分。

然後,以語法。沒有語法錯誤,如果您不介意語法和語義問題的潛在混合,它們都可以順利編譯。

首先,更簡單的語義問題。這不是一個語法問題,但是在兩個版本中,f()都是一個結構的成員,並且該函數顯然不改變擁有的結構,它返回一個常量。儘管該函數被聲明爲constexpr,但它並沒有聲明爲const,這意味着如果有理由將其作爲運行時函數調用,那麼如果嘗試在const S上進行嘗試,則會產生錯誤,這會影響兩個版本。

現在,可能模糊return g(S());顯然,外g是一個函數調用,但因爲這將是如果寫成return g(S{});隨着S可以不那麼清楚{}初始化S,也將在未來沒有歧義應struct S是用一個運算符()擴展(結構幾乎類似於一個仿函數)。被調用的構造函數現在是自動生成的,並且在這個版本中沒有operator()爲編譯器產生混淆,但現代C++ 14應該提供更清晰的選擇來避免「最煩人的分析」,其中g(S ())類似。

所以,我不得不說,基於語義規則,他們都失敗(雖然並不那麼糟糕)。

+0

的成員函數省略常量是無意的,雖然我不知道,如果它會影響示例的不合理性(或其他方面)。以防萬一。 –

+0

爲了清晰起見,我還將默認構造的S更改爲第二個示例中的局部變量。 –

+0

我自己並不是100%,但是它只調用函數顯然作爲const操作的語義問題,但不是(或不是)聲明爲const,所以如果S傳遞爲一個const&S或類似的f()被調用。我實際上以爲你在這裏測試美國;) – JVene

0

我似乎無法在標準中找到一個引人注目的通道或示例,它直接解決了在非constexpr實例上調用constexpr成員函數的問題,但這裏有些可能有所幫助(來自草案N4140 ):

[C++14: 7.1.5/5]

對於非模板,非缺省constexpr功能或非模板,非默認的,非繼承 constexpr構造中,如果沒有參數的值是否存在,使得調用函數或構造函數 可能是一個eval一個核心常量表達式(5.19)的子表達式,該程序是不合格的;沒有 需要診斷。

constexpr int f(bool b) 
    { return b ? throw 0 : 0; }  // OK 
constexpr int f() { return f(true); } // ill-formed, no diagnostic required 

從這個我認爲這個節目是不是完全形成不良僅僅因爲一個constexpr函數有一個可能的非constexpr路徑。

[C++14: 5.19]

int x; // not constant 
struct A { 
    constexpr A(bool b) : m(b?42:x) { } 
    int m; 
}; 
constexpr int v = A(true).m; // OK: constructor call initializes 
          // m with the value 42 
constexpr int w = A(false).m; // error: initializer for m is 
           // x, which is non-constant 

這是稍微接近於您的示例程序,這裏constexpr構造可以根據參數的值引用非constexpr變量,但沒有錯誤,如果這條道路是沒有實際採取。

所以我不認爲呈現兩個程序應該形成不良的,但我不能提供令人信服地證明:)

相關問題