2016-08-12 2 views
2
#include <deque> 
#include <vector> 

struct A 
{ 
    A(int* const p) : m_P(p) {} 
    A(A&& rhs)  : m_P(rhs.m_P) { rhs.m_P = nullptr; } 
    A& operator=(A&& rhs) { delete m_P; m_P = rhs.m_P; rhs.m_P = nullptr; } 
    ~A() { delete m_P; } 

    A(A const& rhs)   = delete; 
    A& operator=(A const& rhs) = delete; 

    int* m_P; 
}; 

int main() 
{ 
#ifdef DDDEQUE 
    std::vector<std::pair<int, std::deque<A> > > vd; 
    vd.emplace(vd.end(), 1, std::deque<A>()); 
#endif // #ifdef DDDEQUE 

    std::vector<std::pair<int, std::vector<A> > > vv; 
    vv.emplace(vv.end(), 1, std::vector<A>()); 
} 

Si la compilation avec g ++ 4.8.5, 5.2.0, 5.3.0 et -DDDDEQUE je reçois un message d'erreur bavard se terminant parC++ std :: deque question constructeur de copie

.../bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(const A&)’ 
    { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } 
    ^
gcc.cpp:11:5: note: declared here 
     A(A const& rhs)   = delete; 

sans -D... compile OK . Avec VC2015, VC2012 les deux versions se compilent correctement. Est-ce que deque (mais pas vector) a besoin du constructeur de copie pour gcc?

+2

Non connecté, il vous manque une valeur 'return' dans votre opérateur d'affectation de mouvement. Et fwiw, vous pouvez ajouter clang 3.8 à la liste des chaînes d'outils compilées avec même lorsque 'DDDEQUE' est défini. – WhozCraig

+0

Cela semble plus une question sur gcc. Alors peut-être 'gcc' devrait être une étiquette. Btw, toute différence si vous utilisez 'vd.emplace (vd.end(), 1, std :: move (std :: deque ()));' à la place? – Walter

Répondre

3

Cela semble être spécifique à libstdC++ (gcc); compte tenu du code ci-dessous;

struct A 
{ 
    A() {}; 
    A(A&&) noexcept { } 
    A& operator=(A&&) noexcept { return *this; } 
    ~A() { } 
}; 

int main() 
{ 
    std::vector<A> a; 
    a.push_back(A{}); // or emplace(a.end()... etc. 
    std::vector<std::deque<A>> b; 
    b.push_back(std::deque<A>()); 
    std::vector<std::pair<int,A>> c; 
    c.push_back(std::pair<int,A>{}); 
    std::vector<std::pair<int,std::deque<A>>> d; 
    d.push_back(std::pair<int,std::deque<A>>{}); 
} 

G ++ ne parvient pas à compiler b et d, clang compile tous les 4 (sauf peut-être d en fonction de la version de libC++ utilisé) et MSVC compile tous les 4 cas (en utilisant leur propre bibliothèque standard associée, avec libstdC++, clang échoue également b et d).

Est-ce que deque (mais pas vector) a besoin du constructeur de copie pour gcc?

Il semble que oui gcc nécessite toujours le constructeur de copie.


En termes plus formels; en C++ 03 std::deque exigeait que le type utilisé dans le conteneur soit Copie Constructible et Copie affectable. Cela a changé en C++ 11, les exigences ont été assouplies, bien qu'un type complet soit généralement toujours requis - étant donné l'échantillon OP, votre bibliothèque standard nécessite toujours la construction et l'affectation de la copie.

De la référence liée;

T - Le type des éléments.

T doit satisfaire aux exigences de CopyAssignable et CopyConstructible. (jusqu'à C++ 11)

Les exigences imposées aux éléments dépendent des opérations réelles effectuées sur le conteneur. Généralement, il est requis que le type d'élément soit un type complet et réponde aux exigences effaçable, mais de nombreuses fonctions membres imposent des exigences plus strictes. (depuis C++ 11)

+1

"* Cela a changé dans C++ 11, vous pourriez chercher à utiliser le niveau de langue pour activer les fonctions *", move-constructor, 'emplace',' deleted', ce sont toutes des fonctionnalités C++ 11 (= OP a déjà C++ 11 activé) –

+0

@PiotrSkotnicki. Je me rends compte que - mais son code nécessite encore le constructeur de copie, etc. – Niall

+0

vecteur a la même exigence relâchée, j'ai lu la question en tant que: «quelle opération provoque deque exiger la construction de la copie" –