簡體   English   中英

如何在靜態constexpr類成員中使用make_tuple()?

[英]How to use make_tuple() in static constexpr class member?

我試圖在constexpr使用make_tuple() 它適用於全球范圍。 但是它為static constexpr類成員生成鏈接錯誤。

#include <iostream>
#include <tuple>

using namespace std;

class A
{
public:
    static constexpr auto z = make_tuple(5, 3.0);
};

constexpr auto tp = make_tuple(6, 3.2);

int main()
{

    cout << get<0>(tp) << " " << get<1>(tp) << endl; // OK

    cout << get<0>(A::z) << "  " << get<1>(A::z) << endl; // error: (.text+0x5a): undefined reference to `A::z'
                                                          //        (.text+0x67): undefined reference to `A::z'

}

我在這里檢查 make_tuple本身不是c++11constexpr 我想在這種情況下這不是問題。 如果是這樣,它將生成一個編譯錯誤而不是鏈接錯誤。

我試圖像下面的答案所示constexpr婁一樣在類外定義constexpr

class A
{
public:
    static constexpr tuple<int, double> z;
};

constexpr tuple<int, double> A::z = make_tuple(5, 3.0);

但是,它會產生幾個編譯錯誤。 根據使用靜態函數初始化靜態成員constexpr的答案,這比較合理

static constexpr類成員中使用make_tuple的正確方法是什么?

編譯器: g++ 4.8.4clang 3.4 -std=c++11

在C ++ static constexpr如果使用ODR,則必須在某個位置定義 static constexpr變量(使用ODR的意思是“以需要身份的方式使用”)。例如,使用真實的引用或指針。這里的ODR表示“一個定義規則”,而ODR所使用的意思是“在某種意義上使用,要求它只有一個定義”,我簡稱為“具有身份”。

只需添加:

constexpr tuple<int, double> A::z;

並定義了它的存在位置。 這必須在一個編譯單元中。

在C ++ 17中,添加了inline變量,並且我相信constexpr變量是隱式內聯的。 我不是C ++ 17專家,但是沒有定義就可以在C ++ 1z模式編譯和運行 ,因此我的解釋似乎至少是正確的一半。

inline變量,像inline函數一樣,最終在編譯器需要的地方創建定義。 inline函數通常是通過在每個對象文件中都有一個帶有特殊注釋的對象的定義來實現的,當有人獲取它的地址時,然后將重復項丟棄在鏈接時間,每個人都指最后一個站。我不知道inline變量是否傾向於以相同的方式實現。)

如果要在C ++ 11中解決此問題而不必在帶有硬編碼模板參數的.cpp文件中放入某些內容,請將z更改為constexpr函數 ,並在要使用它時調用它。


正如SergyA所提到的,ODR在這里被觸發是因為get返回對該元組中某個字段的引用 ,並且該引用暗示該字段以及整個元組必須存在一個標識。

從理論上講,精心設計的由value返回的value_get可以避免這種ODR使用,但這將取決於tuple的實現,因為它反過來又不能調用get

暫無
暫無

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

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