2017-04-04 31 views
3

爲什麼std::get對於std::tuple有這麼多過載(http://en.cppreference.com/w/cpp/utility/tuple/get)?一個對應const&&&的每種可能的組合?對於每個組合,返回值上的const ref限定符是相同的。爲什麼不只有一個通過轉發引用接受元組類型的重載,然後根據輸入的簽名簡單地轉發返回值?像這樣爲什麼std :: get沒有一個接受轉發參考的簽名

template <int Index, typename TupleType> 
decltype(auto) get(TupleType&& tup); 

這樣的事情會讓它變得很容易讓人們有理由對get的功能是什麼,並能避免類似問題2485(https://wg21.cmeerw.net/lwg/issue2485)錯誤

回答

4

std::get存在之前decltype(auto)。這很簡單。

好吧,爲什麼不改變它呢?

std::get的主體沒有被標準規定,不應該是不同的編譯器有不同的元組佈局和實現。

decltype(auto)不告訴讀者標準,編譯器的用戶或實現者,返回類型是什麼。它只是說它是從身體推斷出來的。標準沒有指定。

像這樣的標準將是無用的,除非他們描述了什麼樣的返回值是分開的,最終看起來很像列表超負荷。

+3

應該指出的是,實現可以自由使用'decltype(auto)'並且只是一次過載。 –

+0

@Yakk這是否意味着在類似的情況下,當返回值可以是右值或基於類型扣減的左值時,使用decltype(auto)會是一個糟糕的設計決定?我是否應該有4個重載? – Curious

+0

@curious你是一個標準委員會文檔接口,但不是數百萬程序員和編譯器作家的實現嗎?如果是,那麼這是一個壞主意。如果不是,那麼我的回答並不包括你的情況,你的情況不夠「相似」。如果你有一個完全不同的問題需要回答,請檢查它是否適合在stackoverflow上發佈,如果是這樣的話,請按「提問」按鈕並寫下來。我不打算在評論主題中列出優點和缺點。 – Yakk

2

無法推導出std::get的參數,因爲std::get是針對許多不同類型定義的。 (例如,tuple,pair,arrayvariant)。

由於這個原因,比其他任何std::get都不能推斷出它的參數類型。在此處將其更改爲演繹將會破壞真實世界的代碼,例如從元組推導出的類型。例如,建議的簽名更改會產生如下簽名: template <class TupleLike, class = enable_if_t<IsStdTuple<TupleLike>::value>>> decltype(auto) get(TupleLike&&);

此簽名不允許向接口中的元組類型進行隱式轉換,如舊簽名所做的那樣。如前所述,這會將來自std::tuple的類型或具有轉換運算符的類型分解爲std::tuple

LibC++實施tuple,pairarray使用單個通用TupleLike過載轉換構造函數。作爲維護人員,我非常熟悉這些實現問題,並且如果我可以按照您的建議執行符合要求的std::get,我已經會這樣做。

+2

我不認爲帶有轉換函數的類型對'tuple'工作無論如何。但是,從'tuple'派生的類型應該可以工作。 –

+0

您可以使用模板模板參數和'std :: is_convertible'的組合來檢查參數是否可以轉換爲元組,或更一般地轉換爲模板模板參數? – Curious

+0

@Curious你不能使用'is_convertible',因爲你不知道要檢查什麼'tuple'的特化。 @ T.C具有轉換運算符到元組的類型應該可行,但編譯器前端存在很多實現差異。 – EricWF

相關問題