【问题标题】:Unable to emplace_back instance of a class with const members无法 emplace_back 具有 const 成员的类的实例
【发布时间】:2014-03-28 17:29:17
【问题描述】:

在具有 const 成员的类的实例上使用“emplace_back”时遇到问题。

请参阅下面的示例代码清单。

#include <vector>
using std::vector;

class Data {
  public:
    Data(int a, int b, int c) : a(a), b(b), c(c) {}

    // Removing any/all of these constructors changes nothing!
    Data& operator=(const Data& s) = default;
    Data(const Data& s) = default;
    Data(Data&& s) = default;
    ~Data() = default;

    const int a;
    const int b;
    const int c;
};


int main() {
  vector<Data> v;
  Data e(1,2,3);

  // Problem line
  v.emplace_back(4,5,6);
}

编译错误:

% clang++ a.cc  -std=c++11

In file included from a.cc:1:
In file included from /usr/include/c++/4.6/vector:69:
/usr/include/c++/4.6/bits/vector.tcc:319:16: error: overload resolution selected
      deleted operator '='
          *__position = _Tp(std::forward<_Args>(__args)...);
          ~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/4.6/bits/vector.tcc:102:4: note: in instantiation of function
      template specialization 'std::vector<Data, std::allocator<Data>
      >::_M_insert_aux<int, int, int>' requested here
          _M_insert_aux(end(), std::forward<_Args>(__args)...);
          ^
a.cc:25:5: note: in instantiation of function template specialization
      'std::vector<Data, std::allocator<Data> >::emplace_back<int, int, int>'
      requested here
  v.emplace_back(4,5,6);
    ^
a.cc:9:11: note: candidate function has been explicitly deleted
    Data& operator=(const Data& s) = default;
          ^
In file included from a.cc:1:
In file included from /usr/include/c++/4.6/vector:60:
/usr/include/c++/4.6/bits/stl_algobase.h:546:18: error: overload resolution
      selected deleted operator '='
            *--__result = std::move(*--__last);
            ~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/4.6/bits/stl_algobase.h:578:14: note: in instantiation of
      function template specialization 'std::__copy_move_backward<true, false,
      std::random_access_iterator_tag>::__copy_move_b<Data *, Data *>' requested
      here
      return std::__copy_move_backward<_IsMove, __simple,
             ^
/usr/include/c++/4.6/bits/stl_algobase.h:588:19: note: in instantiation of
      function template specialization 'std::__copy_move_backward_a<true, Data
      *, Data *>' requested here
      return _BI2(std::__copy_move_backward_a<_IsMove>
                  ^
/usr/include/c++/4.6/bits/stl_algobase.h:659:14: note: in instantiation of
      function template specialization 'std::__copy_move_backward_a2<true, Data
      *, Data *>' requested here
      return std::__copy_move_backward_a2<true>(std::__miter_base(__first),
             ^
/usr/include/c++/4.6/bits/vector.tcc:313:4: note: in instantiation of function
      template specialization 'std::move_backward<Data *, Data *>' requested
      here
          _GLIBCXX_MOVE_BACKWARD3(__position.base(),
          ^
/usr/include/c++/4.6/bits/stl_algobase.h:664:48: note: expanded from:
#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::move_backward(_Tp, _Up, _Vp)
                                               ^
/usr/include/c++/4.6/bits/vector.tcc:102:4: note: in instantiation of function
      template specialization 'std::vector<Data, std::allocator<Data>
      >::_M_insert_aux<int, int, int>' requested here
          _M_insert_aux(end(), std::forward<_Args>(__args)...);
          ^
a.cc:25:5: note: in instantiation of function template specialization
      'std::vector<Data, std::allocator<Data> >::emplace_back<int, int, int>'
      requested here
  v.emplace_back(4,5,6);
    ^
a.cc:9:11: note: candidate function has been explicitly deleted
    Data& operator=(const Data& s) = default;
          ^
2 errors generated.

看到这个错误信息:

a.cc:9:11: note: candidate function has been explicitly deleted
        Data& operator=(const Data& s) = default;

我尝试定义一个赋值运算符(以及移动和复制构造函数,以及一个析构函数)以确保隐式生成的运算符不会以某种方式变为私有。这并没有改变什么。在这种情况下,我不明白为什么赋值运算符被“显式删除”。

请注意,将类成员更改为非常量不会导致编译错误。

【问题讨论】:

  • 注意:const(或引用,就此而言)成员无法更改,因此很难编写复制/移动赋值或移动构造函数,包括编译器生成的构造函数。
  • 是的,这是有道理的。但是,我不明白为什么具有 const 成员的类不允许使用复制构造函数?看中间的错误信息a.cc:9:11: note: candidate function has been explicitly deleted:Data&amp; operator=(const Data&amp; s) = default;

标签: c++ c++11 vector default-constructor emplace


【解决方案1】:

您的 clang 版本是什么,您的代码可以使用 clanggcc

当然,不可能默认operator=,因为它会更新const成员失败,但是vector只需要MoveConstructible/CopyConstructible并且不要使用operator=并且你的代码是合法的。

【讨论】:

  • 我有 Ubuntu clang 版本 3.0-6ubuntu3
  • 我下载了 clang 3.4 二进制文件,我得到了相同的错误消息(有或没有构造函数/运算符定义)。
  • clang 只是一个编译器,如果它已经过时,你的标准库(libc++ 或 libstdc++)和 gcc(对于 ld)也可能会更新。
  • 我将 gcc 更新到 4.8 版并安装了 libstdc++6。这似乎没有影响任何事情
  • 还必须更新 g++(当然!)。现在按预期工作,谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 2012-03-02
  • 2019-05-27
  • 1970-01-01
相关资源
最近更新 更多