簡體   English   中英

與定義的類相同類型的靜態constexpr成員

[英]static constexpr member of same type as class being defined

我希望C類有一個類型為C的靜態constexpr成員。這在C ++ 11中是否可行?

嘗試1:

struct Foo {
    constexpr Foo() {}
    static constexpr Foo f = Foo();
};
constexpr Foo Foo::f;

g ++ 4.7.0說:'無效使用不完整類型'指的是Foo()調用。

嘗試2:

struct Foo {
    constexpr Foo() {}
    static constexpr Foo f;
};
constexpr Foo Foo::f = Foo();

現在問題是在類定義中缺少constexpr成員f的初始化器。

嘗試3:

struct Foo {
    constexpr Foo() {}
    static const Foo f;
};
constexpr Foo Foo::f = Foo();

現在g ++抱怨在constexpr重新聲明Foo::f不同。

如果我正確地解釋標准,那是不可能的。

(§9.4.2/ 3)[...]可以使用constexpr說明符在類定義中聲明文字類型的靜態數據成員; 如果是這樣,它的聲明應指定一個大括號或等於初始化器,其中作為賦值表達式的每個initializer子句都是一個常量表達式。 [...]

從上面(以及靜態數據成員聲明中沒有關於非文字類型的單獨聲明的事實),我認為constexpr的靜態數據成員必須是文字類型 (如§3.9/中所定義) 10),它一定有它包含在聲明中定義 使用以下代碼可以滿足后一種情況:

struct Foo {
  constexpr Foo() {}
  static constexpr Foo f {};
};

這與您的嘗試1類似,但沒有類外部定義。

但是,由於在聲明/定義靜態成員時Foo不完整,編譯器無法檢查它是否是文字類型(如§3.9/ 10中所定義),因此它拒絕代碼。

請注意, 這篇后C ++ - 11文檔(N3308)討論了標准中當前constexpr定義的各種問題,並提出修改建議。 具體而言,“建議的措辭”部分建議對§3.9/ 10進行修訂,這意味着將不完整類型作為一種文字類型。 如果要將該修訂納入標准的未來版本,您的問題將得到解決。

我認為GCC拒絕您的嘗試3是不正確的.C ++ 11標准(或其任何已接受的缺陷報告)中沒有規則表明如果事先聲明的話,變量的重新聲明必須是constexpr 最接近該規則的標准是[dcl.constexpr](7.1.5)/ 1_

如果函數或函數模板的任何聲明都有constexpr規范,則其所有聲明都應包含constexpr規范。

Clang對constexpr的實施接受了你的嘗試3。

理查德史密斯答案的更新,現在嘗試3編譯GCC 4.9和5.1,以及叮叮3.4。

struct Foo {
  std::size_t v;
  constexpr Foo() : v(){}
  static const Foo f;
};

constexpr const Foo Foo::f = Foo();

std::array<int, Foo::f.v> a;

但是,當Foo是類模板時,clang 3.4失敗,但GCC 4.9和5.1仍然可以正常工作:

template < class T >
struct Foo {
  T v;
  constexpr Foo() : v(){}
  static const Foo f;
};

template < class T >
constexpr const Foo<T> Foo<T>::f = Foo();

std::array<int, Foo<std::size_t>::f.v> a; // gcc ok, clang complains

Clang錯誤:

error: non-type template argument is not a constant expression
std::array<int, Foo<std::size_t>::f.v> a;
                ^~~~~~~~~~~~~~~~~~~~~

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM