g ++ -std = c ++ 0x出现意外的编译问题

aka*_*ppa 8 c++ c++11

我有一些编译问题在使用g ++ -std = c ++ 0x进行编译时将类型T的元素推回到向量.

这是一个最小的例子:

#include <vector>

using namespace std;

class A {
public:
    A() { }

    A& operator=(A &orig) {
        return *this;
    }
};

int main(int argc, char **argv) {
    A a;
    vector<A> b;
    A c = a; // This is fine
    b.push_back(a); // This is not, but only when compiling with -std=c++0x!
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它使用g ++ -Wall -pedantic编译得很好,但是在使用g ++ -Wall -pedantic -std = c ++ 0x进行编译时会出现此错误:

 In file included from /usr/include/c++/4.4/vector:69,
                 from min.cpp:1:
/usr/include/c++/4.4/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = const A&, _Tp = A, _Alloc = std::allocator<A>]’:
/usr/include/c++/4.4/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = A, _Alloc = std::allocator<A>]’
min.cpp:20:   instantiated from here
/usr/include/c++/4.4/bits/vector.tcc:314: error: no match for ‘operator=’ in ‘__position.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = A*, _Container = std::vector<A, std::allocator<A> >]() = ((const A&)((const A*)std::forward [with _Tp = const A&](((const A&)((const A*)__args#0)))))’
min.cpp:11: note: candidates are: A& A::operator=(A&)
In file included from /usr/include/c++/4.4/vector:61,
                 from min.cpp:1:
/usr/include/c++/4.4/bits/stl_algobase.h: In static member function ‘static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = A*, _BI2 = A*]’:
/usr/include/c++/4.4/bits/stl_algobase.h:595:   instantiated from ‘_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = A*, _BI2 = A*]’
/usr/include/c++/4.4/bits/stl_algobase.h:605:   instantiated from ‘_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = A*, _BI2 = A*]’
/usr/include/c++/4.4/bits/stl_algobase.h:676:   instantiated from ‘_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = A*, _BI2 = A*]’
/usr/include/c++/4.4/bits/vector.tcc:308:   instantiated from ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = const A&, _Tp = A, _Alloc = std::allocator<A>]’
/usr/include/c++/4.4/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = A, _Alloc = std::allocator<A>]’
min.cpp:20:   instantiated from here
/usr/include/c++/4.4/bits/stl_algobase.h:561: error: no match for ‘operator=’ in ‘* -- __result = std::move [with _Tp = A&](((A&)(-- __last)))’
min.cpp:11: note: candidates are: A& A::operator=(A&)
Run Code Online (Sandbox Code Playgroud)

所以似乎找不到合适的算子= A.为什么?为什么它说with _Iterator = A*我何时通过A?

AnT*_*AnT 15

语言标准对标准容器元素所强加的可分配要求要求t = u表达式即使u是const对象也是有效的.这个要求是从C++ 98开始定义的(参见23.1/4)

您违反了该要求,因为您的赋值运算符不接受const对象.这立即意味着您的类A不能用作容器元素类型.

为什么它在C++ 03中起作用是相当无关紧要的.它偶然起作用.从错误消息中可以明显看出,库的C++ 0x实现使用了一些C++ 0x特定的功能(例如std::move),这就是上述要求发挥作用的原因.但无论如何,C++ 03实现(甚至C++ 98实现)也可能无法为您编译A.

你的例子A c = a;是无关紧要的,因为它根本不使用赋值运算符(为什么它在这里?).

为了修复错误,您应该通过const引用或值接受参数.

  • @akappa:自从C++ 98以来,*Assignable*的要求就在那里.因此,在任何版本的标准C++中,代码通常都是不可编译的.只是在GCC实现的前C++ 0x标准中,你很幸运,错误滑过了.但在C++ 0x中不再是这种情况. (4认同)
  • @akappa:`A c = a;`根本不使用赋值,因此在这里不相关(它使用复制构造).`A; c = a;`正在讨论什么.; - ] (3认同)