简体   繁体   English

无法从大括号括起来的初始化列表转换为std元组

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

As part of a bigger project, I'm playing with std::tuple and templates; 作为一个更大的项目的一部分,我正在玩std::tuple和模板; consider the following code: 考虑以下代码:

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;
}

According to this answer C++17 supports tuple initialization from copy-list-initialization , however it seems such support is limited since I get the following error (GCC 7.2.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
                 ^

Is there any way I can use brace-enclosed syntax in this scenario? 在这种情况下,我有什么方法可以使用大括号括起来的句法吗?

Some Context : this is going to be used in an operator overload so I guess I'm bound to tuples and cannot make use of variadics, any hint is well-accepted. 一些上下文 :这将在运算符重载中使用,所以我猜我已经绑定了元组并且无法使用可变参数,任何提示都被广泛接受。

Extra : Clang 6 also complains 额外 :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) {}

A braced-init-list , like {1, 'S'} , does not actually have a type. {1, 'S'}这样的braced-init-list实际上并没有类型。 In the context of template deduction, you can only use them in certain cases - when deducing against initializer_list<T> (where T is a function template parameter) or when the corresponding parameter is already deduced by something else. 在模板推导的上下文中,您只能在某些情况下使用它们 - 当针对initializer_list<T> (其中T是函数模板参数)进行推导时,或者当相应参数已经由其他内容推断时。 In this case, neither of those two things is true - so the compiler cannot figure out what ...T is supposed to be. 在这种情况下,这两件事都不是真的 - 所以编译器无法弄清楚...T应该是什么。

So you can provide the types directly: 所以你可以直接提供类型:

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

Or you can construct the tuple yourself and pass that in: 或者您可以自己构建tuple并将其传递给:

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

Today, ClassTemplate<Ts...> can only be deduced from expressions of type ClassTemplate<Us...> or types that inherit from something like that. 今天, ClassTemplate<Ts...>只能从ClassTemplate<Us...>类型的表达式或从类似的东西继承的类型推断出来。 A hypothetical proposal could extend that to additionally try to perform class template argument deduction on the expression to see if that deduction succeeds. 假设的提议可以扩展到另外尝试对表达式执行类模板参数推断以查看该推导是否成功。 In this case, {1, 'S'} isn't a tuple<Ts...> but tuple __var{1, 'S'} does successfully deduce tuple<int, char> so that would work. 在这种情况下, {1, 'S'}不是tuple<Ts...>但是tuple __var{1, 'S'}成功推导出tuple<int, char>以便这样做。 Such a proposal would also have to address issues like... what if we're deducing ClassTemplate<T, Ts...> or any minor variation, which isn't something that class template argument deduction allows (but is something that many people have at times expressed interest in being able to do). 这样的提议还必须解决诸如......如果我们推断ClassTemplate<T, Ts...>或任何微小的变化,这不是类模板参数演绎允许的内容(但是很多东西人们有时表示有兴趣这样做。

I'm not aware of such a proposal today. 我今天不知道这样的建议。

According to this answer C++17 supports tuple initialization from copy-list-initialization, however it seems such support is limited since I get the following error 根据这个答案,C ++ 17支持从copy-list-initialization开始的元组初始化,但是看起来这样的支持是有限的,因为我得到以下错误

The problem is another. 问题是另一个问题。

When you call bar({1, 'S'}) , the compiler knows that bar() receive a tuple<int, char> , so take 1 as int and 'S' as char . 当你调用bar({1, 'S'}) ,编译器知道bar()接收一个tuple<int, char> ,所以将1作为int ,将'S'作为char

See another example: if you define 请参阅另一个示例:如果您定义

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

you can call 你可以打电话

baz(1);

because the compiler knows that baz() receive a std::tuple<int> so take 1 to initialize the int in the tuple. 因为编译器知道baz()接收到std::tuple<int>所以取1来初始化元组中的int

But with 但随着

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

the compiler doesn't know the T... types; 编译器不知道T...类型; when you call 你打电话的时候

foo({1, 'S'}); 

what T... types should deduce the compiler? 什么T...类型应该推断编译器?

I see, at least, two hypothesis: T = int, char or T = std::pair<int, char> ; 我看到,至少有两个假设: T = int, charT = std::pair<int, char> ; or also T = std::tuple<int, char> . 或者还有T = std::tuple<int, char>

Which hypothesis should follows the compiler? 编译器应遵循哪种假设?

I mean: if you pass a std::tuple to foo() , the compiler accept the list of types in the tuple as the list of T... ; 我的意思是:如果你将std::tuple传递给foo() ,编译器会接受元组中的类型列表作为T...的列表; but if you pass something else, the compiler must deduce the correct std::tuple ; 但是如果你传递别的东西,编译器必须推导出正确的std::tuple ; but this deduction, in this case, is not unique. 但在这种情况下,这种推论并不是唯一的。 So the error. 所以错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法从大括号括起来的初始化列表转换为std :: vector - Could not convert from brace-enclosed initializer list to std::vector 错误:无法从 '<brace-enclosed initializer list> ' 到 'std::tuple<void (xxx::*)(), xxx> '</void></brace-enclosed> - error: could not convert from '<brace-enclosed initializer list>' to 'std::tuple<void (xxx::*)(), xxx>' 错误:无法转换&#39; <brace-enclosed initializer list> ()&#39;从&#39; <brace-enclosed initializer list> &#39;到&#39;结构&#39; - Error: could not convert '<brace-enclosed initializer list>()' from '<brace-enclosed initializer list>' to 'struct' 无法转换&#39; <brace-enclosed initializer list> 至 - Could not convert from '<brace-enclosed initializer list> to 无法将…转换为&#39; <brace-enclosed initializer list> 到地图 - could not convert … from '<brace-enclosed initializer list>' to map 无法从转换 <brace-enclosed initializer list> 到int(*)数组 - Could not convert from <brace-enclosed initializer list> to int(*) array 无法从转换<brace-enclosed initializer list> - could not convert from <brace-enclosed initializer list> 无法从 '<brace-enclosed initializer list> ' 到 map</brace-enclosed> - could not convert from ‘<brace-enclosed initializer list>’ to map 无法转换{...} <brace-enclosed initializer list> 结构 - could not convert {…} from <brace-enclosed initializer list> to struct 无法从大括号括起来的初始化列表转换 - Could not convert from brace-enclosed initializer list
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM