无法从大括号括起来的初始值设定项列表转换为标准元组
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 支持从 copy-list-initialization 进行元组初始化,但似乎这种支持是有限的,因为我收到以下错误 ( 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
^
有什么方法可以在这种情况下使用大括号括起来的语法吗?
Some Context :这将在运算符重载中使用,所以我想我绑定到元组并且不能使用可变参数,任何提示都可以接受.
额外: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,与 {1, 'S'}
一样,实际上没有类型。在模板推导的上下文中,您只能在某些情况下使用它们 - 当针对 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...>
类型的表达式或从类似类型继承的类型中推导出来。一个假设的提议可以扩展它以另外尝试对表达式执行 class 模板参数推导以查看该推导是否成功。在这种情况下,{1, 'S'}
不是 tuple<Ts...>
,但 tuple __var{1, 'S'}
确实成功地推断出 tuple<int, char>
,因此它可以工作。这样的提案还必须解决以下问题......如果我们推导 ClassTemplate<T, Ts...>
或任何微小的变化,这不是 class 模板参数推导允许的(但很多人们有时表示有兴趣能够做到)。
我今天不知道有这样的提议。
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
问题是另一个。
当你调用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, char
或 T = std::pair<int, char>
;或者 T = std::tuple<int, char>
.
编译器应该遵循哪个假设?
我的意思是:如果你将 std::tuple
传递给 foo()
,编译器接受元组中的类型列表作为 T...
的列表;但是如果你传递别的东西,编译器必须推断出正确的 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;
}
根据
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
^
有什么方法可以在这种情况下使用大括号括起来的语法吗?
Some Context :这将在运算符重载中使用,所以我想我绑定到元组并且不能使用可变参数,任何提示都可以接受.
额外: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,与 {1, 'S'}
一样,实际上没有类型。在模板推导的上下文中,您只能在某些情况下使用它们 - 当针对 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...>
类型的表达式或从类似类型继承的类型中推导出来。一个假设的提议可以扩展它以另外尝试对表达式执行 class 模板参数推导以查看该推导是否成功。在这种情况下,{1, 'S'}
不是 tuple<Ts...>
,但 tuple __var{1, 'S'}
确实成功地推断出 tuple<int, char>
,因此它可以工作。这样的提案还必须解决以下问题......如果我们推导 ClassTemplate<T, Ts...>
或任何微小的变化,这不是 class 模板参数推导允许的(但很多人们有时表示有兴趣能够做到)。
我今天不知道有这样的提议。
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
问题是另一个。
当你调用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, char
或 T = std::pair<int, char>
;或者 T = std::tuple<int, char>
.
编译器应该遵循哪个假设?
我的意思是:如果你将 std::tuple
传递给 foo()
,编译器接受元组中的类型列表作为 T...
的列表;但是如果你传递别的东西,编译器必须推断出正确的 std::tuple
;但在这种情况下,这种推论并不是唯一的。所以报错。