[英]std::pair<auto, auto> return type
我在std::pair
玩弄auto
。 在下面的代碼中,函數f
應該返回依賴於模板參數的std::pair
類型。
一個工作示例:
例 1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
這適用於 gcc 9.2、gcc 10.0、clang 9.0 和 clang 10.0。
接下來,為了清晰起見,我想將返回類型顯式寫為std::pair
:
例2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
gcc 9.2/10.0 和 clang 9.0/10.0 都無法編譯這個。
海灣合作委員會 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
從最后一條錯誤消息來看,gcc 9.2 似乎認為std::pair<auto, auto>
是一個int
。 這怎么解釋?
海灣合作委員會 10.0
error: returning initializer list
這個錯誤是可以理解的,但是,我希望調用std::pair
的構造函數,或者我在這里遺漏了什么?
叮當 9.0 和 10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
好吧,clang 不喜歡這些。 從第二條錯誤消息來看,似乎 clang 也認為返回類型是int
。
最后,為了修復使用 gcc 10.0 編譯時出現的錯誤,我決定明確返回一個std::pair
:
例3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
叮當 9.0 和 10.0
和以前一樣,但有一個額外的:
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
這里 clang 仍然認為我們正在返回一個int
?
海灣合作委員會 9.2
和之前一樣。
海灣合作委員會 10.0
有用!
我想某些功能仍然需要實現,或者在上述一種情況下,是否有一個正確的編譯器和另一個錯誤的編譯器? 在我看來,示例 2 應該有效。 或者不應該?
語法:
std::pair<auto, auto> f() { return std::pair(1, 2); }
~~~~~~~~~~~~~~~~~~~~~
是原始概念 TS 的一部分,但未包含在作為 C++20 一部分的概念提案中。 因此,C++20 中唯一的占位符類型是auto
(及其變體,如auto**
)、 decltype(auto)
和受約束的占位符( Concept auto
及其變體)。 這種嵌套的占位符類型非常有用,但不是 C++20 的一部分,因此函數聲明是格式錯誤的。
現在,gcc 允許它,因為 gcc 實現了概念 TS,我猜他們決定保留這個功能。 clang 從未實現過 TS,所以它沒有。
無論哪種方式,這:
std::pair<auto, auto> f() { return {1, 2}; }
永遠是畸形的。 語法的含義是我們推導出返回類型,然后要求它與某些類型T
和U
pair<T, U>
匹配。 我們基本上是在嘗試調用發明的函數:
template <typename T, typename U>
void __f(std::pair<T, U>);
__f({1, 2}); // this must succeed
但是您不能從{1, 2}
推導出類型 - 花括號初始化列表沒有類型。 也許這是應該探索的事情(因為至少在這樣的簡單案例中很容易理解),但從未被允許。 因此,無論哪種方式,拒絕它都是正確的。
最后:
gcc 9.2 似乎相信
std::pair<auto, auto>
是一個int
。 這怎么解釋?
出於某種原因(可能是由於我們的 C 遺留的隱式int
),當 gcc 無法識別或理解類型時,它只是使用int
作為錯誤消息中的占位符。 這非常令人困惑,因為顯然是 gcc 提出了int
而不是源代碼。 但事情就是這樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.