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

Ostatni wiersz daje błąd: 17 : error: invalid conversion from 'const char*' to 'char' [-fpermissive]Idealne spedycja zawodzi, gdy cel jest kruszywo z tablicy

Jeśli używam std::forward(args)... zamiast args... następnie nawet więcej błędów wymyślić; a także są błędy, gdy próbuję użyć {'a', 'b', 'c', '\0'} jako inicjalizatora zamiast literału.

Czy istnieje sposób, aby to działało, to znaczy pozwolić X z{......}; gdzie wszystko wewnątrz szelki że byłoby initializer prawną x2, jest akceptowana i czy faktycznie zainicjować x2?

+0

"* Czy istnieje sposób, aby to działało" *, usunąć konstruktora lub użyj 'std :: string' jako typ' buf' –

+0

pisanie ' 'a', 'b',” c ',' \ 0'' zamiast '" abc "' działa z VS używając C++ 17 –

Odpowiedz

5

Jest to niepewna kwestia projektowania, która została odziedziczona po C++ 98: niektóre konwersje lub inicjalizacje są ograniczone syntaktycznie do literałów, w szczególności literały łańcuchowe jako inicjatory dla tablic znaków ([dcl.init.string]/1) i liczby całkowite jako stałe wskaźnika pustego ([conv.ptr]/1). To oczywiście nie pasuje do "doskonałej" spedycji.

W przypadku wskaźników zerowych problem omijano wprowadzając nullptr, którego można użyć zamiast 0 i działa poprawnie nawet po przesłaniu dalej.

W twoim przypadku, nie są w zasadzie dwie główne opcje:

  • Exploit nawiasów elizja - X jest agregatem też:

    struct X { 
        X2 x2; 
    } z{1, 2, "abc"}; // Ok 
    
  • stwierdzenie buf mieć typ klasy, na przykład std::string lub, być może bardziej odpowiedni w twoim przypadku, odpowiednik o rozmiarach statycznych (ograniczony do rozmiaru 10).

+0

zmartwiony, miałem na myśli, że ogólnie 'X' nie byłby agregatem, mój pomysł polegał na zezwalaniu na nieagregaty z wiele danych publicznych, aby nadal wykorzystywać agregacyjną inicjalizację dla tych danych publicznych –