2016-01-25 20 views
20

Wygląda na to, że dodanie domyślnego konstruktora uniemożliwia wywołanie emplace_back i generuje komunikat o błędzie: "Asercja statyczna nie powiodła się: typ nie jest możliwy do przypisania" (gcc 5.3 z opcją -std = C++ 14). Oto prosty kod, który ilustruje problem:Domyślny konstruktor uniemożliwia wywoływanie emplace_back

class A { 
public: 
    int a; 
    A() = default; 
    A(int a) { 
     this->a = a; 
    } 
    A(A const & a) = delete; 
    A& operator =(A const & a) = delete; 
    A(A && a) = default; 
    A& operator =(A && a) = default; 
}; 

int main() { 

    A a(4); 
    std::vector<A> vec; 
    vec.emplace_back(std::move(a)); // Error: type is not assignable 
    return 0; 
} 

Po usunięciu domyślnego konstruktora błąd zniknie! Ponadto, jeśli konstruktor domyślny jest zdefiniowany (nawet jeśli to nic nie robi), błąd idzie również z dala:

class A { 
public: 
    int a; 
    A() { 
    } 
    A(int a) { 
     this->a = a; 
    } 
    A(A const & a) = delete; 
    A& operator =(A const & a) = delete; 
    A(A && a) = default; 
    A& operator =(A && a) = default; 
}; 

int main() { 

    A b; 
    A a(4); 
    std::vector<A> vec; 
    vec.emplace_back(std::move(a)); // Error gone 
    return 0; 
} 

Wydaje się, że „() = default;” jest przyczyną problemu. Czy to normalne zachowanie na części kompilatora lub jest to błąd?

+0

[clang] (http://coliru.stacked-crooked.com/a/1c9da1c732899237) wyświetla to samo zachowanie, co gcc – jaggedSpire

+0

Kod kompiluje się dobrze z gcc 4.7.2 pod C++ 11 –

+2

Wpływa na trywialność klasa. –

Odpowiedz

15

To błąd biblioteki libstdC++ (edycja: zgłoszona jako bug 69478).

skrócie libstdC++ „s std::vector, jak istotne tutaj, wykorzystuje std::uninitialized_copy (sparowany z iteratorów ruchu), aby przenieść elementy na realokacji, który jest redukowany do std::copy jeśli typ jest trywialne, a iteratory” typy referencyjne są przypisane (czyli przyporządkowanie operator, który byłby koncepcyjnie użyty, jest użyteczny).

Następnie std::copy dla wskaźniki do trywialnych typów (lub w naszym przypadku, move_iterator owijania wskaźnik) z kolei jest zoptymalizowany do wywołania memmove połączeniu z czekiem na is_copy_assignable. Oczywiście kontrola ta jest w tym przypadku błędna, ponieważ uninitialized_copy, w połączeniu z iteratorami ruchu, wymaga jedynie, aby przedmiot był ruchomy.

Jeśli nie masz domyślnego konstruktora lub jeśli domyślny konstruktor jest zdefiniowany przez użytkownika, to klasa nie jest trywialna, więc nie trafisz na ścieżkę kodu, która wyzwala ten błąd.

+0

Dzięki za odpowiedź. –

Powiązane problemy