2015-12-19 30 views
7
#include <iostream> 

struct X2 
{ 
    int i; 
    int j; 
    char buf[10]; 
}; 

X2 glob{1,2,"abc"}; // OK 

struct X 
{ 
    X2 x2; 

    template<typename... Args> 
    X(Args&&... args): x2{args...} {} 
}; 

int main() 
{ 
    X x;    // OK 
    X y{1, 2};   // OK 
    X z{1, 2, "abc"}; // error 
} 

L'ultima riga fornisce errore: 17 : error: invalid conversion from 'const char*' to 'char' [-fpermissive]perfetta trasmissione fallisce quando il bersaglio è aggregato con matrice

Se uso std::forward(args)... anziché args... allora anche più errori venire; e inoltre ci sono errori se provo a usare {'a', 'b', 'c', '\0'} come inizializzatore invece della stringa letterale.

C'è un modo per fare questo lavoro, vale a dire consentire X z{......}; dove tutto all'interno delle parentesi graffe che sarebbe un inizializzatore legale per x2, viene accettato e in effetti inizializza x2?

+0

"* C'è un modo per fare questo lavoro" *, rimuovere il costruttore, o utilizzare 'std :: STRING' come il tipo di' buf' –

+0

scrittura ' 'a', 'b',' c ',' \ 0'' invece di '" abc "' funziona con VS usando C++ 17 –

risposta

5

Questo è un problema di progettazione precario che è stato ereditato da C++ 98: alcune conversioni o inizializzazioni sono sintatticamente limitate ai letterali, in particolare stringhe letterali come inizializzatori per gli array di caratteri ([dcl.init.string]/1) e valori letterali interi come costanti puntatore nullo ([conv.ptr]/1). Questo, ovviamente, non si sposa bene con l'inoltro "perfetto".

Per i puntatori nulli, il problema è stato eluso introducendo nullptr, che può essere utilizzato al posto di 0 e funziona bene anche dopo essere stato inoltrato.

Nel tuo caso, ci sono fondamentalmente due opzioni principali:

  • Exploit brace elisione - X è un aggregato, troppo:

    struct X { 
        X2 x2; 
    } z{1, 2, "abc"}; // Ok 
    
  • Dichiarare buf avere tipo di classe, per esempio std::string o, forse più appropriato nel tuo caso, qualche equivalente in dimensioni statiche (limitato alla dimensione 10).

+0

scusate, volevo dire che in generale 'X' non sarebbe un aggregato, la mia idea era di consentire i non aggregati con un molti dati pubblici continuano a utilizzare l'inizializzazione aggregata per i dati pubblici –