2015-12-19 4 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 
} 

Die letzte Zeile gibt Fehler: 17 : error: invalid conversion from 'const char*' to 'char' [-fpermissive]Perfect Forwarding schlägt fehl, wenn Ziel mit Array-Aggregat ist

Wenn ich std::forward(args)... statt args... dann noch mehr Fehler kommen; und außerdem gibt es Fehler, wenn ich versuche, {'a', 'b', 'c', '\0'} als Initialisierer anstelle des Zeichenfolgenliterals zu verwenden.

Gibt es eine Möglichkeit, diese Arbeit zu machen, damit das heißt X z{......};, wo alles in den Klammern, die eine rechtliche Initialisierer für x2 sein würde, angenommen wird und dadurch nicht in x2 initialisieren?

+0

"* Gibt es eine Möglichkeit, diese Arbeit zu machen" *, entfernen Sie den Konstruktor, oder verwenden Sie 'std :: string' als Art der' buf' –

+0

Schreiben ' 'a', 'b',‘ c ',' \ 0'' statt '" abc "' arbeitet mit VS unter Verwendung von C++ 17 –

Antwort

5

Dies ist ein prekäres Design-Problem, das von C++ 98 geerbt wurde: Bestimmte Konvertierungen oder Initialisierungen sind syntaktisch auf Literale beschränkt, insbesondere String-Literale als Initialisierer für char-Arrays ([dcl.init.string]/1) und Ganzzahlliterale als Nullzeigerkonstanten ([conv.ptr]/1). Das passt natürlich nicht zur "perfekten" Weiterleitung.

Für Nullzeiger wurde das Problem umgangen, indem nullptr eingeführt wurde, das anstelle von 0 verwendet werden kann und funktioniert auch nach Weiterleitung einwandfrei.

In Ihrem Fall gibt es im Grunde zwei Hauptoptionen sind:

  • Exploit Klammer elision - X ein Aggregat ist, auch:

    struct X { 
        X2 x2; 
    } z{1, 2, "abc"}; // Ok 
    
  • buf deklarieren Klassentyp zu haben, z.B. std::string oder, vielleicht in Ihrem Fall, etwas statischer Größe gleichwertig (begrenzt auf Größe 10).

+0

Entschuldigung, ich meinte, dass im Allgemeinen 'X' kein Aggregat wäre, meine Idee war es, Nicht-Aggregate mit einem zuzulassen Viele öffentliche Daten, die weiterhin die Aggregat-Initialisierung für diese öffentlichen Daten verwenden –