Sva*_*zen 7 c++ initialization language-lawyer std-pair c++20
考虑以下代码:
#include <utility>
#include <vector>
using V = std::vector<int>;
int main() {
std::pair<int, V> p1{1, 2}; // p1.second has 2 elements
std::pair<int, V> p2{1, {2}}; // p2.second has 1 element
std::pair<V, V> p3{2, 2}; // Both vectors have 2 elements
std::pair<V, V> p4{{2}, {2}}; // Both vectors have 1 element
std::pair<V, V> p5{2, {2}}; // Does not compile
// p5.first should have 2 elements, while the other should have 1
}
Run Code Online (Sandbox Code Playgroud)
我的主要问题是最后一行 ,p5它不能编译,g++-12但可以编译g++-10。我想知道:
V(2)某处使用)我也尝试过玩,std::piecewise_construct但我不确定这是否是正确的解决方案。
错误:
<source>: In function 'int main()':
<source>:9:30: error: no matching function for call to 'std::pair<std::vector<int>, std::vector<int> >::pair(<brace-enclosed initializer list>)'
9 | std::pair<V, V> p3{2, {2}};
| ^
In file included from /opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/utility:69,
from <source>:1:
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:354:9: note: candidate: 'template<class _U1, class _U2> requires _S_constructible<_U1, _U2>() && _S_dangles<_U1, _U2>() constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&) [with _U2 = _U1; _T1 = std::vector<int>; _T2 = std::vector<int>]' (deleted)
354 | pair(pair<_U1, _U2>&&) = delete;
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:354:9: note: template argument deduction/substitution failed:
<source>:9:30: note: mismatched types 'std::pair<_T1, _T2>' and 'int'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:345:9: note: candidate: 'template<class _U1, class _U2> requires _S_constructible<_U1, _U2>() && !_S_dangles<_U1, _U2>() constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&) [with _U2 = _U1; _T1 = std::vector<int>; _T2 = std::vector<int>]'
345 | pair(pair<_U1, _U2>&& __p)
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:345:9: note: template argument deduction/substitution failed:
<source>:9:30: note: mismatched types 'std::pair<_T1, _T2>' and 'int'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:339:9: note: candidate: 'template<class _U1, class _U2> requires _S_constructible<const _U1&, const _U2&>() && _S_dangles<const _U1&, const _U2&>() constexpr std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U2 = _U1; _T1 = std::vector<int>; _T2 = std::vector<int>]' (deleted)
339 | pair(const pair<_U1, _U2>&) = delete;
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:339:9: note: template argument deduction/substitution failed:
<source>:9:30: note: mismatched types 'const std::pair<_T1, _T2>' and 'int'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:330:9: note: candidate: 'template<class _U1, class _U2> requires _S_constructible<const _U1&, const _U2&>() && !_S_dangles<_U1, _U2>() constexpr std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U2 = _U1; _T1 = std::vector<int>; _T2 = std::vector<int>]'
330 | pair(const pair<_U1, _U2>& __p)
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:330:9: note: template argument deduction/substitution failed:
<source>:9:30: note: mismatched types 'const std::pair<_T1, _T2>' and 'int'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:323:9: note: candidate: 'template<class _U1, class _U2> requires _S_constructible<_U1, _U2>() && _S_dangles<_U1, _U2>() constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U2 = _U1; _T1 = std::vector<int>; _T2 = std::vector<int>]' (deleted)
323 | pair(_U1&&, _U2&&) = delete;
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:323:9: note: template argument deduction/substitution failed:
<source>:9:30: note: couldn't deduce template parameter '_U2'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:315:9: note: candidate: 'template<class _U1, class _U2> requires _S_constructible<_U1, _U2>() && !_S_dangles<_U1, _U2>() constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U2 = _U1; _T1 = std::vector<int>; _T2 = std::vector<int>]'
315 | pair(_U1&& __x, _U2&& __y)
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:315:9: note: template argument deduction/substitution failed:
<source>:9:30: note: couldn't deduce template parameter '_U2'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:238:9: note: candidate: 'template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> constexpr std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {_Args1 ...}; long unsigned int ..._Indexes1 = {_Indexes1 ...}; _Args2 = {_Args2 ...}; long unsigned int ..._Indexes2 = {_Indexes2 ...}; _T1 = std::vector<int>; _T2 = std::vector<int>]'
238 | pair(tuple<_Args1...>&, tuple<_Args2...>&,
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:238:9: note: template argument deduction/substitution failed:
<source>:9:30: note: mismatched types 'std::tuple<_UTypes ...>' and 'int'
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:202:9: note: candidate: 'template<class ... _Args1, class ... _Args2> constexpr std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {_Args1 ...}; _Args2 = {_Args2 ...}; _T1 = std::vector<int>; _T2 = std::vector<int>]'
202 | pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:202:9: note: template argument deduction/substitution failed:
<source>:9:30: note: candidate expects 3 arguments, 2 provided
9 | std::pair<V, V> p3{2, {2}};
| ^
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:305:7: note: candidate: 'constexpr std::pair<_T1, _T2>::pair(const _T1&, const _T2&) requires _S_constructible<const _T1&, const _T2&>() [with _T1 = std::vector<int>; _T2 = std::vector<int>]'
305 | pair(const _T1& __x, const _T2& __y)
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:305:23: note: no known conversion for argument 1 from 'int' to 'const std::vector<int>&'
305 | pair(const _T1& __x, const _T2& __y)
| ~~~~~~~~~~~^~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:249:7: note: candidate: 'constexpr std::pair<_T1, _T2>::pair() requires (is_default_constructible_v<_T1>) && (is_default_constructible_v<_T2>) [with _T1 = std::vector<int>; _T2 = std::vector<int>]'
249 | pair()
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:249:7: note: candidate expects 0 arguments, 2 provided
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:198:17: note: candidate: 'constexpr std::pair<_T1, _T2>::pair(std::pair<_T1, _T2>&&) [with _T1 = std::vector<int>; _T2 = std::vector<int>]'
198 | constexpr pair(pair&&) = default; ///< Move constructor
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:198:17: note: candidate expects 1 argument, 2 provided
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:197:17: note: candidate: 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = std::vector<int>; _T2 = std::vector<int>]'
197 | constexpr pair(const pair&) = default; ///< Copy constructor
| ^~~~
/opt/compiler-explorer/gcc-trunk-20230315/include/c++/13.0.1/bits/stl_pair.h:197:17: note: candidate expects 1 argument, 2 provided
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
这看起来像是一个错误修复(适用于 C++20 及更低版本)。没有正确实现的 C++ 版本:
\nstd::pair<V, V> p5{2, {2}};\nRun Code Online (Sandbox Code Playgroud)\n会编译。
\n花括号初始化列表/初始化列表(注意缺少“_”)不是表达式;它是它自己独立的语法结构。它参与模板参数推导的方式确实非常简单。
\n(大部分)没有。
\n如果相应的参数显式地是initializer_list<E>某种类型的,那么它可以推导出E。否则它不能并且参数是不可推导的:
\n\n\n如果从 P 中删除引用和 cv 限定符给出 std::initializer_list<P\xe2\x80\xb2> 或 P\xe2\x80\xb2[N] 对于某些 P\xe2\x80\xb2 和 N 并且参数是 a非空初始化列表([dcl.init.list]),然后对初始化列表的每个元素独立执行推导,将 P\xe2\x80\xb2 作为单独的函数模板参数类型 P\xe2\x80\xb2i并将第 i 个初始值设定项元素作为相应的参数。\n在 P\xe2\x80\xb2[N] 情况下,如果 N 是非类型模板参数,则从初始值设定项列表的长度推导出 N。\n否则,初始值设定项列表参数导致该参数被视为非推导上下文 ([temp.deduct.type])。
\n
\n\n关联参数是初始值设定项列表 ([dcl.init.list]) 的函数参数,但该参数不具有指定从初始值设定项列表推导的类型 ([temp.deduct.call])。
\n
当然,如果无法推导模板参数,则模板参数推导失败,并且无法调用该函数。
\n\n\n如果模板参数仅在非推导上下文中使用并且未显式指定,则模板参数推导将失败。
\n
这意味着构造函数如下:
\ntemplate< class U1, class U2 >\npair( U1&& x, U2&& y );\nRun Code Online (Sandbox Code Playgroud)\n不适用于花括号初始化列表。因此,唯一可行的构造函数{2, {2}}是第二个参数不是需要推导的模板参数的构造函数。
这基本上意味着这个:
\n对(常量 T1& x,常量 T2& y );
\nT1和T2来自类模板参数,而不是函数模板的参数。您已经将它们指定为Vand V,以便尝试调用。
但是,vector<int>不能从整数 2隐式转换explicit。采用单个整数的构造函数是,因此尝试初始化x将失败。
该构造函数自 C++98 以来一直是显式的。所以永远不std::pair<V, V> p5{2, {2}};应该工作。如果确实如此,则这是实施中的一个错误。
请注意,C++23 更改了s 构造函数之一pair以具有默认模板参数:
template< class U1 = T1, class U2 = T2 >\npair( U1&& x, U2&& y );\nRun Code Online (Sandbox Code Playgroud)\n这将允许{2, {2}}语法工作,因为它不再依赖模板参数推导来获取模板参数类型。
\n\n是否可以再次编译而无需构建向量并将它们复制进去(即不在某处使用 V(2) )
\n
这从来没有奏效。它总是复制一份。
\n您可以使用piecewise_construct体操initializer_list来避免“复制”。但实际上,只需切换到使用 atuple并在初始化列表中正确使用该类型:
std::tuple<V, V> p5{V{2}, V{2}};\nRun Code Online (Sandbox Code Playgroud)\n或者,减少冗余:
\nstd::tuple p5{V{2}, V{2}};\nRun Code Online (Sandbox Code Playgroud)\n这将从参数中移动,而不是从参数中复制。
\n\n\n但是,我不太清楚这是否可以回答为什么两个“对称”调用
\np(2, 2)和p({2},{2})编译没有问题,并且只有在不对称时才会中断。
后者之所以有效,是因为它调用T1, T2构造函数,该构造函数可以隐式地将花括号初始化列表转换为vector.
前者之所以有效,是因为U1, U2构造函数会将它们推导为两个整数。并且 avector可以从整数构造(但不能隐式转换)。因此,这两个Vs 可以通过从这些参数直接初始化来构造。
非对称的不起作用,因为花括号初始化列表的存在U1, U2完全关闭了构造函数,因为U2无法推断(同样,直到 C++23)。