Why const member caused error?

#include <vector>

class B {
};

class A {
    const std::vector<B> m_v;
public:
    A(const std::vector<B>& v) : m_v(v) {}
    void doSomething() {}
};

void foo(void* bar) {
    A* a = (A*)bar;
    a->doSomething();
}

int main() {
    std::vector<B> v;
    std::vector<A > l;
    for (auto i = 0; i < 10; i++) {
        A a(v);
        l.push_back(std::move(a));
        foo((void*)&l[i]);
    }
    return 0;
}
$ g++ -Wall initList.cpp -o initList -lrt -O3 -std=c++0x
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/vector:70:0,
                 from initList.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc: In member function u2018void std::vector::_M_insert_aux(std::vector::iterator, _Args&& ...) [with _Args = {A}, _Tp = A, _Alloc = std::allocator, std::vector::iterator = __gnu_cxx::__normal_iterator >, typename std::_Vector_base::_Tp_alloc_type::pointer = A*]`:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:102:4:   instantiated from u2018void std::vector::emplace_back(_Args&& ...) [with _Args = {A}, _Tp = A, _Alloc = std::allocator]`
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_vector.h:840:9:   instantiated from u2018void std::vector::push_back(std::vector::value_type&&) [with _Tp = A, _Alloc = std::allocator, std::vector::value_type = A]`
initList.cpp:23:27:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:319:4: error: use of deleted function '& A::operator=(const A&)`
initList.cpp:6:7: error: '& A::operator=(const A&)` is implicitly deleted because the default definition would be ill-formed:
initList.cpp:6:7: error: passing u2018const std::vector` as u2018this` argument of u2018std::vector& std::vector::operator=(const std::vector&) [with _Tp = B, _Alloc = std::allocator]` discards qualifiers [-fpermissive]
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/vector:61:0,
                 from initList.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h: In static member function u2018static _BI2 std::__copy_move_backward::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = A*, _BI2 = A*]`:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:581:18:   instantiated from u2018_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = A*, _BI2 = A*]`
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:590:34:   instantiated from u2018_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = A*, _BI2 = A*]`
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:661:15:   instantiated from u2018_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = A*, _BI2 = A*]`
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:313:4:   instantiated from u2018void std::vector::_M_insert_aux(std::vector::iterator, _Args&& ...) [with _Args = {A}, _Tp = A, _Alloc = std::allocator, std::vector::iterator = __gnu_cxx::__normal_iterator >, typename std::_Vector_base::_Tp_alloc_type::pointer = A*]`
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:102:4:   instantiated from u2018void std::vector::emplace_back(_Args&& ...) [with _Args = {A}, _Tp = A, _Alloc = std::allocator]`
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_vector.h:840:9:   instantiated from u2018void std::vector::push_back(std::vector::value_type&&) [with _Tp = A, _Alloc = std::allocator, std::vector::value_type = A]`
initList.cpp:23:27:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:546:6: error: use of deleted function '& A::operator=(const A&)`

If I don't specify const for m_v. It compiles fine.

The error suggests something with assign operator, which I don't see how it is invoked.

Any idea?

Thanks in advance.


It's a bug in older versions of GCC/libstdc++, your code compiles fine with GCC 4.8.1. Live example . The bug is triggered by

l.push_back(std::move(a));

as older versions of GCC tried to create a default-constructed element in the vector and assigned the parameter std::move(a) to it in a second step instead of using the in-place copy/move-ctor.

链接地址: http://www.djcxy.com/p/66742.html

上一篇: 如何从函数返回对?

下一篇: 为什么const成员造成错误?