2013-02-20 13 views
6

Voglio creare una struttura con 3 valori: una stringa e due int. La stringa è obbligatoria, ma uno (o entrambi) degli interi è facoltativo e può essere impostato su -1 se non specificato.posizionare oggetti derivanti da tuple in un vettore in C++

Tuttavia, piuttosto che utilizzare una struttura, ho pensato di provare una std :: tupla. Al fine di integrare l'opzione-ness dei due interi, a configurare una classe di "Trio" che eredita da std :: tuple, come di seguito:

#include <string> 
#include <tuple> 

class Trio : public std::tuple<std::string, int, int> 
{ 
    public: 

    explicit Trio(std::string const & name, int val1 = -1, int val2 = -1) 
    : 
     tuple(name, val1, val2) 
    { 
    } 
}; 

Poi vado a testare la classe Trio spingendo alcuni oggetti Trio in uno std :: vector:

#include <vector> 
int main(void) 
{ 
    std::vector<Trio> trios; 

    Trio trio("trio1", 1, 1); 
    trios.push_back(trio); 

    return 0; 
} 

mi dà il seguente errore in Visual Studio 2010:

>c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple(127): 
    error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const 
    std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 
    from 'const Trio' to 'const std::basic_string<_Elem,_Traits,_Ax> &' 
with 
[ 
    _Elem=char, 
    _Traits=std::char_traits<char>, 
    _Ax=std::allocator<char> 
] 
Reason: cannot convert from 'const Trio' to 'const 
std::basic_string<_Elem,_Traits,_Ax>' 
with 
[ 
    _Elem=char, 
    _Traits=std::char_traits<char>, 
    _Ax=std::allocator<char> 
] 
No user-defined-conversion operator available that can perform 
this conversion, or the operator cannot be called 

qualcuno capire quello che sto facendo in modo errato qui? C'è qualcosa di ovvio che non sto vedendo? Sto forse abusando gravemente dell'uso di std :: tuple?

Grazie,

Aaron

+0

Compila OK su ideone: http://ideone.com/9q0nxW – Bill

+0

Questo compilato per me con g ++ http://ideone.com/ZAIDUp – juanchopanza

risposta

8

Si tratta di un bug di VC10.

VC10 si lamenta perché la classe non corrisponde a per avere un costruttore di copie. Pertanto, per copiare i valori di tipo Trio, tenta di convertirli in string, che è ciò che accetta il costruttore che gli viene fornito (altri argomenti possono avere valori predefiniti). Questo è ciò che l'errore che si ottiene si lamenta:

non può convertire il parametro 1 da 'Trio const' a 'std const :: basic_string < _Elem, _Traits, _Ax> &'

Potete verificare che questo è davvero quello che sta succedendo con l'aggiunta di un costruttore di copia in modo esplicito e guardare l'errore scompare:

Trio(Trio const& t) { *this = t; } 

Ora VC10 è soddisfatto perché vede un costruttore di copia, e il codice compila bene.

Tuttavia, quando nessun costruttore di copia è esplicitamente fornito dall'utente, il compilatore dovrebbe generarne uno implicitamente. Per Paragrafo 12.8/7 del C++ 11 standard:

Se la definizione della classe non dichiara esplicitamente un costruttore di copia, si è dichiarata implicitamente. Se la definizione della classe dichiara un costruttore di spostamenti o un operatore di spostamento, il costruttore di copie dichiarato implicitamente viene definito come eliminato; altrimenti, è definito come predefinito (8.4). [...]

Classe Trio non dichiara esplicitamente alcun costruttore di copia. Secondo l'articolo 12.8/2 del C++ 11 standard, infatti:

Un costruttore non template per la classe X è un costruttore di copia se il suo primo parametro è di tipo X &, const X &, volatile X & o const X volatili &, e uno non ci sono altri parametri, altrimenti tutti gli altri parametri sono gli argomenti di default (8.3.6)

Così, il costruttore si fornisce in modo esplicito è non un costruttore di copia e dovrebbe non inibisce la generazione implicita di un costruttore di copie.

VC10 probabilmente interpreta erroneamente il costruttore fornito come costruttore di copia e, pertanto, non ne genera uno implicitamente. A causa di quello scritto sopra, tuttavia, questo comportamento è una corretta e si qualifica come bug. (*)

Come nota a margine, il codice compila bene su Clang 3.2, GCC 4.7.2, e ICC 13,0. 1.

UPDATE:

ho cercato di riprodurre il problema con strutture di dati semplici che non comportano std::tuple<>, e ho fallito. Pertanto, il bug non è semplicemente dovuto al fatto che il costruttore è interpretato erroneamente da VC10 come costruttore di copie esplicite. Tuttavia, ciò non cambia il fatto che il comportamento di VC10 non è corretto.

+1

+1 per completezza e riferimento allo standard. – pstrjds

+0

Che ha funzionato. Ho aggiunto un costruttore di copie esplicito a Trio, e ora compila bene. Grazie!!! – Aaron

+0

@ Aaron: sono contento che mi abbia aiutato :-) –

1

Sembra che questo è solo un problema in VS2010. Non ho guardato per vedere se c'è un bug archiviato o no. Questo compilerà sia in VS2012 e gcc-4.7.2

+0

Grazie. Non so perché VS2010 non generi un costruttore di copia per Trio, ma sicuramente non si compilerà senza uno esplicito. – Aaron

Problemi correlati