从 initializer_list 初始化向量会产生不明确的编译错误

Posted

技术标签:

【中文标题】从 initializer_list 初始化向量会产生不明确的编译错误【英文标题】:initializing a vector from an initializer_list generates an unclear compilation error 【发布时间】:2020-10-05 17:04:32 【问题描述】:

如果std::copy 被注释掉并且atc 初始化器被取消注释,则此代码编译。

class MyClass 
  MyClass( OtherClass* poc_in, std::initializer_list<ThirdClass> iltc) :
    poc( poc_in)
    //, atc(iltc)
  
    std::copy( iltc.begin(), iltc.end(), atc );
  

  OtherClass* poc;
  std::vector<ThirdClass> atc;

但是,正如我所写的:

In file included from /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/algorithm:61:0,
                 from ../../../src/tester/main.cpp:5:
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/stl_algobase.h: In instantiation of '_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const ThirdClass*; _OI = std::vector<ThirdClass>]':
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/stl_algobase.h:422:45:   required from '_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const ThirdClass*; _OI = std::vector<ThirdClass>]'
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/stl_algobase.h:455:8:   required from '_OI std::copy(_II, _II, _OI) [with _II = const ThirdClass*; _OI = std::vector<ThirdClass>]'
../../../src/tester/main.cpp:75:59:   required from here
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/stl_algobase.h:378:57: error: no type named 'value_type' in 'struct std::iterator_traits<std::vector<ThirdClass> >'
       typedef typename iterator_traits<_OI>::value_type _ValueTypeO;
                                                         ^~~~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/stl_algobase.h:383:9: error: no type named 'value_type' in 'struct std::iterator_traits<std::vector<ThirdClass> >'
       const bool __simple = (__is_trivial(_ValueTypeI)
                             ~~~~~~~~~~~~~~~~~~~~~~~~~~
                       && __is_pointer<_II>::__value
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                       && __is_pointer<_OI>::__value
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         && __are_same<_ValueTypeI, _ValueTypeO>::__value);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我在 Stack Overflow 上阅读了六个类似的问题,但没有一个能够阐明为什么这个版本不受欢迎。有什么建议吗?

【问题讨论】:

什么是ThirdClass?出示您的minimal reproducible example。 @SamVarshavchik 实际上,您会发现,一旦修复了编译错误,它就可以正常工作了。因为这就是修复所达到的效果。 【参考方案1】:

这与初始化列表无关。

你用错了std::copy

第三个参数应该是一个输出迭代器,而不是一个向量。

尝试使用std::back_inserter

std::copy( iltc.begin(), iltc.end(), std::back_inserter(atc) );

编译错误确实有点深奥,但它表示编译器正在为参数类型在特征帮助器中寻找成员value_typeall大多数迭代器都有)你给了它(一个向量),它不存在(因为向量不是迭代器)。

【讨论】:

the cppreference page for std::copy 上甚至还有一个例子!没有必要在 Stack Overflow 上阅读六个类似的问题...... 谢谢。我也读过那个页面,但没有意识到我的代码与所写的不匹配。除了你在这里建议的 back_inserter() 之外,atc.begin() 呢?这似乎是在几个例子中。它是否应该以同样的方式工作,您是否看到任何一种方式的优点或缺点? 主要的缺点是它不能正常工作。您在向量中没有任何元素,因此您无法写入从atc.begin() 开始的序列。如果你用准备覆盖的元素预先填充向量,你可以这样做。但是,要创建 new 元素,您需要 back_inserter(因此得名)。

以上是关于从 initializer_list 初始化向量会产生不明确的编译错误的主要内容,如果未能解决你的问题,请参考以下文章

在向量映射上使用 initializer_list

如何在初始化期间将 std::initializer_list 转换为列矩阵或列向量?

元组向量和 initializer_list

列表初始化使用啥构造函数

初始化列表initializer_list

标记为“显式”的 C++11 initializer_list 构造函数