簡體   English   中英

為什么 constexpr 靜態成員(類型類)需要定義?

[英]Why does constexpr static member (of type class) require a definition?

==> 在coliru上查看完整的代碼片段和編譯。

我有一個LiteralType類填充constexpr要求

struct MyString
{
    constexpr MyString(char const* p, int s) : ptr(p), sz(s) {}
    constexpr char const* data() const { return ptr; }
    constexpr int         size() const { return sz;  }

    char const *ptr = 0;
    int  const  sz  = 0;
};

我將它用作constexpr static成員變量:

struct Foo
{
    int size() { return str_.size(); }

    constexpr static MyString str_{"ABC",3};
};

int main()
{
  Foo foo;
  return ! foo.size();
}

但是鏈接器說:
(Clang-3.5 和 GCC-4.9)

undefined reference to `Foo::str_'

我必須定義constexpr static成員!
(我沒有指定構造函數參數)

constexpr MyString Foo::str_;

但是,如果constexpr static成員是int則不必在類定義之外定義該成員。 這是我的理解,但我不確定...

問題:

  • 為什么int不需要在類聲明之外定義,但MyString需要這個?
  • 在頭文件中定義constexpr static成員是否有缺點?
    (我只提供我的庫作為頭文件)

單一定義規則告訴我們,在一個程序中,一個odr-used變量的定義不能超過一個。 所以如果一個變量是 odr-used 那么你需要定義它,但你不能定義它的頭文件,因為它可能被包含在整個程序中不止一次。 Odr 使用違規不需要診斷消息,因此您可以違反此規則,編譯器沒有義務通知您。

在您的情況下,您確實是使用 odr 的str_ ,並且您不能在頭文件中包含該定義,因為這將違反一個定義規則,因為它可以在程序中多次包含。

有趣的是,如果您執行了以下操作,則不會使用 odr:

return str_.size_;

因此,您不需要定義變量,這在某些示例中可能會產生一些奇怪的后果 我懷疑這是否真的能長期解決你的問題。

odr 規則包含在 C++ 標准草案第3.2節中,他們說:

變量 x 其名稱顯示為潛在求值表達式 ex 是 odr-used 除非將左值到右值轉換 (4.1) 應用到 x 產生一個不調用任何非平凡函數的常量表達式 (5.19) 並且,如果x 是一個對象,ex 是表達式 e 的潛在結果集合中的一個元素,其中左值到右值的轉換(4.1)應用於 e,或者 e 是丟棄值表達式(第 5 條)。 如果它作為潛在評估的表達式出現(包括作為非靜態成員函數 (9.3.1) 的主體中的隱式轉換的結果),則 this 被使用。[...]

所以str_產生一個常量表達式,左值到右值的轉換沒有應用表達式str_.size()並且它不是丟棄值表達式,因此它是 odr-used ,因此需要定義str_

另一方面,左值到右值的轉換應用於表達式str_.size_ ,因此它不是 odr 使用的,也不需要定義str_

暫無
暫無

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

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