簡體   English   中英

無法從大括號括起來的初始化列表轉換為std元組

[英]Could not convert from brace-enclosed initializer list to std tuple

作為一個更大的項目的一部分,我正在玩std::tuple和模板; 考慮以下代碼:

template <typename ...T> void foo(tuple<T...> t) {}
void bar(tuple<int, char> t) {}
tuple<int, char> quxx() { return {1, 'S'}; }

int main(int argc, char const *argv[])
{
    foo({1, 'S'});           // error
    foo(make_tuple(1, 'S')); // ok
    bar({1, 'S'});           // ok
    quxx();                  // ok
    return 0;
}

根據這個答案, C ++ 17支持從復制列表初始化開始的元組初始化,但是由於我得到以下錯誤(GCC 7.2.0),所以似乎這種支持是有限的:

main.cpp: In function 'int main(int, const char**)':
main.cpp:14:17: error: could not convert '{1, 'S'}' from '<brace-enclosed initializer list>' to 'std::tuple<>'
     foo({1, 'S'}); // error
                 ^

在這種情況下,我有什么方法可以使用大括號括起來的句法嗎?

一些上下文 :這將在運算符重載中使用,所以我猜我已經綁定了元組並且無法使用可變參數,任何提示都被廣泛接受。

額外 :Clang 6也抱怨

prog.cc:12:5: error: no matching function for call to 'foo'
    foo({1, 'S'});           // error
    ^~~
prog.cc:6:31: note: candidate function [with T = <>] not viable: cannot convert initializer list argument to 'tuple<>'
template <typename ...T> void foo(tuple<T...> t) {}

{1, 'S'}這樣的braced-init-list實際上並沒有類型。 在模板推導的上下文中,您只能在某些情況下使用它們 - 當針對initializer_list<T> (其中T是函數模板參數)進行推導時,或者當相應參數已經由其他內容推斷時。 在這種情況下,這兩件事都不是真的 - 所以編譯器無法弄清楚...T應該是什么。

所以你可以直接提供類型:

foo<int, char>({1, 'S'});

或者您可以自己構建tuple並將其傳遞給:

foo(std::tuple<int, char>(1, 'S')); // most explicit
foo(std::tuple(1, 'S')); // via class template argument deduction

今天, ClassTemplate<Ts...>只能從ClassTemplate<Us...>類型的表達式或從類似的東西繼承的類型推斷出來。 假設的提議可以擴展到另外嘗試對表達式執行類模板參數推斷以查看該推導是否成功。 在這種情況下, {1, 'S'}不是tuple<Ts...>但是tuple __var{1, 'S'}成功推導出tuple<int, char>以便這樣做。 這樣的提議還必須解決諸如......如果我們推斷ClassTemplate<T, Ts...>或任何微小的變化,這不是類模板參數演繹允許的內容(但是很多東西人們有時表示有興趣這樣做。

我今天不知道這樣的建議。

根據這個答案,C ++ 17支持從copy-list-initialization開始的元組初始化,但是看起來這樣的支持是有限的,因為我得到以下錯誤

問題是另一個問題。

當你調用bar({1, 'S'}) ,編譯器知道bar()接收一個tuple<int, char> ,所以將1作為int ,將'S'作為char

請參閱另一個示例:如果您定義

void baz (std::tuple<int> const &)
 { }

你可以打電話

baz(1);

因為編譯器知道baz()接收到std::tuple<int>所以取1來初始化元組中的int

但隨着

template <typename ...T>
void foo(tuple<T...> t)
 { }

編譯器不知道T...類型; 你打電話的時候

foo({1, 'S'}); 

什么T...類型應該推斷編譯器?

我看到,至少有兩個假設: T = int, charT = std::pair<int, char> ; 或者還有T = std::tuple<int, char>

編譯器應遵循哪種假設?

我的意思是:如果你將std::tuple傳遞給foo() ,編譯器會接受元組中的類型列表作為T...的列表; 但是如果你傳遞別的東西,編譯器必須推導出正確的std::tuple ; 但在這種情況下,這種推論並不是唯一的。 所以錯誤。

暫無
暫無

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

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