【问题标题】:std::back_inserter needs const_reference on older GCC. Why?std::back_inserter 需要旧 GCC 上的 const_reference。为什么?
【发布时间】:2026-01-27 02:30:01
【问题描述】:

我目前正在研究一些可以在较新版本的 GCC 上编译但不能在旧版本上编译的代码。在我的情况下,我使用std::back_inserterstd::copy 一些数据从一个数据结构到一个自定义数据结构。但是,如果我忘记了这个自定义数据结构中的typedef value_type & const_reference typedef,这将无法在 GCC 4.4 上编译。相同的代码在 GCC 4.5 上编译和运行都很好。

这两个编译器版本之间有什么区别,这使得代码在一个版本上编译,而在另一个版本上不编译。我猜想这与 C++11 的实现有关,在 GCC 4.4 中它的完成度要低得多。我猜可能是 decltype 或另一个新的 C++11 关键字。

如果我使用std::back_inserter 而不定义const_reference 类型,那么这段代码是否正确?我通常认为必须实现全套 typedef(value_typereferenceconst_reference 等)才能与 STL 算法库兼容?或者我可以安全地假设如果我的代码在这种情况下编译,我没有调用任何危险的东西(例如移动语义,这会破坏我的其他数据结构)。

【问题讨论】:

  • 记录一下(帮助像我这样的初学者节省时间):在我将typedef T& reference; typedef const T& const_reference;添加到我的数据结构后,back_inserter的错误c2039消失了。

标签: c++ stl stl-algorithm


【解决方案1】:

标准 (1998) 说 std::back_insert_iterator 需要 Container::const_reference。在“24.4.2.1 模板类 back_insert_iterator”,[lib.back.insert.iterator] 中,它说:

back_insert_iterator<Container>&
operator=(typename Container::const_reference value);

2011标准只需要Container::value_type

back_insert_iterator<Container>&
operator=(const typename Container::value_type& value);
back_insert_iterator<Container>&
operator=(typename Container::value_type&& value);

因此,要与两个版本的 C++ 标准兼容,请同时定义 value_typeconst_reference_type

在 GCC 4.4.6 和 4.5.1 中,operator= 的定义是相同的 (libstdc++-v3/include/bits/stl_iterator.h):

  back_insert_iterator&
  operator=(typename _Container::const_reference __value)
  {
    container->push_back(__value);
    return *this;
  }

我在两个编译器上都遇到了同样的错误,也许你需要仔细检查你是否使用了正确的编译器版本。

【讨论】:

  • 感谢您的澄清。正如我刚刚验证的那样,在 4.5.2 上它可以在没有 const_reference 类型的情况下工作。 4.4.4 还是需要的。
  • @LiKao,在最近的 GCC 中,默认启用了 C++0x 库兼容性。 GCC4.5.2 比 GCC 4.4 稍微更多兼容:),因为它仅在禁用兼容性时才使用const_reference,而 4.4 无条件使用它。
  • @chill: 引用 the documentation of the current gcc version: The default, if no C++ language dialect options are given, is -std=gnu++98.。所以,你确定你说的是什么?
【解决方案2】:

您需要为数据结构定义 const_reference 的原因是因为 GCC 4.4 中 std::back_insert_iterator 类中左值参数类型的赋值运算符定义为:

template<class Container>
back_insert_iterator<Container>& 
back_insert_iterator<Container>::operator= 
                  (typename Container::const_reference value);

因此,const_reference 需要是类类型中的可解析标识符,才能正确实例化 std::back_insert_iterator 类模板中的赋值运算符。

在 GCC 4.5 中,左值参数的赋值运算符的定义已更改为

template<class Container>
back_insert_iterator<Container>&
back_insert_iterator<Container>::operator=
                 (const typename Container::value_type& value);

为了支持新的 C++11 规范。由于您的代码可以使用 GCC 4.5 正确编译,我假设您必须为您的数据结构正确定义 value_type

【讨论】:

    最近更新 更多