将可变的类型列表的扩展打包为复杂类型的初始化器列表-是否合法?

时间:2018-09-11 06:22:44

标签: c++ c++11 c++14 c++17 stdinitializerlist

我想将可变参数类型列表“物化”为相关值的initializer_list。 例如,具有多个std::tuple的{​​{1}}得到一个std::integral_constant<T, x>。 通常,我想获取一些复杂类型的initializer_list,例如std::initializer_list<T>{...}

但是下面的简单示例让我在用Clang编译时崩溃了(尽管它与GCC兼容,至少在Coliru上有效),所以我怀疑UB(或Clang中的错误):

std::string

Live on Coliru

那么,这样的代码合法吗?在C ++ 11/14/17中?

2 个答案:

答案 0 :(得分:9)

关于initializer_list的两件事:

  

初始化程序列表可以实现为一对指针或指针   和长度。复制std :: initializer_list 不复制   基础对象

  

不能保证基础数组在存在之后就存在   原始的初始化程序列表对象已结束。的存储   std :: initializer_list未指定(即可以是自动的,   临时或静态只读存储器,具体取决于情况)。

所以在这一行

return {
      std::to_string(Ts::value)...
    };

您正在创建本地数组,initializer_list保持指向该数组的开始/结尾的指针,当函数超出范围时,您将拥有悬空的指针。

答案 1 :(得分:3)

std::initializer_list的基础数组实际上是一个本地临时对象。当离开<input type="hidden" name="certid" value="<?php print base64_encode(serialize($result)); ?>"> 时,它已被破坏。复制$data = unserialize(base64_decode($this->input->post('certid'))); 不会复制基础数组,返回的materialize的内容始终无效,尝试访问返回的std::initializer_list的内容会导致UB。

(重点是我的)

  

初始化程序列表可以实现为一对指针或指针   和长度。 复制std :: initializer_list不会复制   基础对象

     

基础数组是类型为std::initializer_list的临时数组,位于   每个元素都被复制初始化(缩小范围除外)   转换无效)   原始的初始化程序列表。基础数组的生命周期是   与其他任何临时对象相同,除了初始化   数组中的initializer_list对象延长了   数组完全类似于将引用绑定到临时(具有相同的   异常,例如用于初始化非静态类成员的异常)。的   基础数组可以分配在只读内存中。