首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套列表初始化如何转发其参数?

嵌套列表初始化如何转发其参数?
EN

Stack Overflow用户
提问于 2020-05-26 20:05:38
回答 2查看 237关注 0票数 2

在对向量的初始化中

代码语言:javascript
复制
  std::vector<std::pair<int, std::string>> foo{{1.0, "one"}, {2.0, "two"}};

我该如何解释foo的结构?据我理解,

  1. 构造函数是用带括号的初始化语法调用的,因此重载vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );是首选和选择的。
  2. std::initializer_list<T>的模板参数导出为std::pair<int, std::string>
  3. foo的每个元素都是一个std::pair。但是,std::pair没有重载接受std::initializer_list

对于第三步,我不太确定。我知道内部大括号不能被解释为std::initializer_list,因为它们是异质的。标准中实际构建foo每个元素的机制是什么?我怀疑答案与将内部大括号中的参数转发到重载template< class U1, class U2 pair( U1&& x, U2&& y );有关,但我不知道这是什么。

编辑

我想问同样的问题的更简单的方法是:

代码语言:javascript
复制
std::map<int, std::string> m = { // nested list-initialization
           {1, "a"},
           {2, {'a', 'b', 'c'} },
           {3, s1}

the首选项示例中所示,在标准中,它表示{1, "a"}{2, {'a', 'b', 'c'} }{3, s1}分别被转发给std::pair<int, std::string>的构造函数

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-27 09:32:45

通常,表达式是从内到外分析的:内部表达式有类型,然后这些类型决定外部操作符的含义和要调用的函数。

但是初始化程序列表不是表达式,也没有类型。因此,内-外不工作.需要特殊的过载解析规则来解释初始化程序列表。

第一条规则是:如果存在一个参数为initializer_list<T>的构造函数,那么在第一轮过载解析中,只考虑此类构造函数(over.match.list)。

第二条规则是:对于每个initializer_list<T>候选项(每个类可能有一个以上的候选项,每个类都有不同的T ),检查每个初始化器是否可以转换为T,并且只有那些候选项保留在这个结果(over.ics.list)中。

这第二个规则基本上是,其中的初始化-列表-有-没有类型的障碍是采取和内-外分析被恢复。

一旦重载解析决定了应该使用特定的initializer_list<T>构造函数,就会使用复制初始化来初始化初始化器的列表。

票数 1
EN

Stack Overflow用户

发布于 2020-05-27 08:19:07

您混淆了两个不同的概念:

1)初始化器列出

initializer_list<T>**:**,主要用于集合的初始化。在这种情况下,所有成员都应该是同一类型的。(不适用于std::pair)

示例:

std::vector<int> vec {1, 2, 3, 4, 5};

2)统一初始化

Uniform initialization:中,大括号用于构造和初始化一些对象,如structs、类(带有适当的构造函数)和基本类型(int、char等)。

示例:

代码语言:javascript
复制
struct X { int x; std::string s;}; 
X x{1, "Hi"}; // Not an initializer_list here.

前面已经提到,对于带有大括号初始化器的std::pair的初始化,您需要一个构造函数,它接受两个元素,即第一个和第二个元素,而不是一个std::initializer_list<T>。例如,在安装了VS2015的机器上,此构造函数如下所示:

代码语言:javascript
复制
template<class _Other1,
    class _Other2,
    class = enable_if_t<is_constructible<_Ty1, _Other1>::value
                    && is_constructible<_Ty2, _Other2>::value>,
    enable_if_t<is_convertible<_Other1, _Ty1>::value
            && is_convertible<_Other2, _Ty2>::value, int> = 0>
    constexpr pair(_Other1&& _Val1, _Other2&& _Val2) // -----> Here the constructor takes 2 input params
        _NOEXCEPT_OP((is_nothrow_constructible<_Ty1, _Other1>::value
            && is_nothrow_constructible<_Ty2, _Other2>::value))
    : first(_STD forward<_Other1>(_Val1)), // ----> initialize the first 
            second(_STD forward<_Other2>(_Val2)) // ----> initialize the second
    {   // construct from moved values
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62030516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档