C++ 标准::初始值设定项列表<;int const>;无法从std::initializer\u list构建<;int>;
我的问题是关于C++ 标准::初始值设定项列表<;int const>;无法从std::initializer\u list构建<;int>;,c++,initializer-list,c++17,C++,Initializer List,C++17,我的问题是关于std::initializer\u list类型之间缺乏转换,其中包含的类型或多或少是cv限定的,而这些转换似乎很容易实现 考虑以下无效代码: std::initializer_list<int> x{1,2,3,4,5,6}; std::initializer_list<int const> y = x; // error! cannot convert! 我假设默认情况下,语言规范要求为std::initializer\U list推导非cv限定的U
std::initializer\u list
类型之间缺乏转换,其中包含的类型或多或少是cv限定的,而这些转换似乎很容易实现
考虑以下无效代码:
std::initializer_list<int> x{1,2,3,4,5,6};
std::initializer_list<int const> y = x; // error! cannot convert!
我假设默认情况下,语言规范要求为std::initializer\U list
推导非cv限定的U
据我所知,std::optional
(和std::any
和std::variant
)具有std::initializer\u list
构造函数重载的整个要点是避免指定初始化器列表的确切类型。要编译上述代码的第二行,您必须这样做
std::initializer\u list
已经为它的数据保存了一个const*
(无论如何,在libc++
中)。我看不出上面的代码有什么不起作用的原因?这在语言中是一个可以解决的问题,还是我遗漏了什么?听起来你的问题是,为什么std::initializer\u list
不能从std::initializer\u list
构建,尽管这样的转换很容易实现
我认为答案是首先不应该有std::initializer\u list
,因为正如您所指出的,std::initializer\u list
只允许const
访问其元素
< P> >因此,可以说C++中有一个“文化规范”,你不应该有任何构造函数,需要一个<代码> STD::例如,没有一个标准库容器会这样做,因为cv限定值类型无论如何都是非法的(除了std::array
,它当然没有用户定义的构造函数)
如果您编写自己的类型MyContainer
支持MyContainer
,那么我建议您将其设置为如下所示:
template <class T>
class MyContainer {
public:
MyContainer(std::initializer_list<std::remove_cv_t<T>> il);
// ...
};
模板
类霉菌容器{
公众:
MyContainer(std::initializer\u list il);
// ...
};
<代码>很难“忽略荒谬的类型”,当代码>向量在C++中是不合法的。那么,您究竟为什么希望初始值设定项\u list
起作用呢?你想用它做什么?老实说,我不知道。当我发现这一点时,我正在编写一个通用包装器类型。也许它对于类似于dynarray
@nicolabolas的某种类型是有意义的,因为我会说vector
意外地是不合法的,它可能在C++17中成为合法的,不是出于意图,而是作为其他行为的副产品changes@M.M当分配器需求表完全禁止它时,这绝非偶然。“文化规范”似乎是正确的!如果有人(你?)可以解释为什么所有初始值设定项列表都没有被推断为std::initializer\u list
,如果它们与std::initializer\u list
@xcvr具有相同的语义,std::initializer\u list
的模板参数是使用模板参数推断的常规规则推导出来的,它永远不会推断cv限定类型、引用类型、数组类型或函数类型。尽管我认为模板参数推断的常规规则不适用于无法推断类型的情况,除非将其指定为std::initializer\u list
。
template <class T>
class MyContainer {
public:
MyContainer(std::initializer_list<std::remove_cv_t<T>> il);
// ...
};