2017-11-06 1 views
1

Bedenken Sie:Emulate Aggregat Initialisierung für rekursiv definierte Array-ähnliche Klasse

template <std::size_t r,std::size_t d> 
struct Tensor 
{ 
    Tensor<r-1u,d> Data[d]; 
}; 

template <std::size_t d> 
struct Tensor<0u,d> 
{ 
    double Data; 
}; 

Wir Kopie-list-Initialisierung eine solche Tensor auf diese Weise initialisieren können:

Tensor<2u,3u> t= { 1.0, 2.0, 3.0, 
        4.0, 5.0, 6.0, 
        7.0, 8.0, 9.0 }; 

Notiere die Klammer elision .

Dies funktioniert auch in einem generischen Programmierkontext, z.B.:

template <typename... T, 
    typename= std::enable_if_t<(std::is_same_v<T,double> && ...) && (sizeof...(T)==9u)>> 
Tensor<2u,3u> MakeTensor(T... x) { return {x...}; } 

Wenn jedoch Data privat waren, Tensor wäre nicht mehr ein Aggregat sein, und somit würde die obige Syntax keine Gültigkeit.

In diesem Fall konnte dieses Verhalten programmgesteuert wiederhergestellt werden?

+0

Aggregat Initialisierung benötigt ein Aggregat, also nicht streng genommen; Sie können es über einen Initialisiererlisten-Konstruktor emulieren, obwohl –

+1

... oder ein Konstruktor, der eine Aggregatversion Ihrer Tensordatenstruktur verwendet, die nur für Initialisierungszwecke verwendet wird –

+0

@MassimilianoJanes Ja. Das könnte funktionieren. Vielleicht "Tensor" in "TensorData" umbenennen, so dass der eigentliche Tensor eine private Instanz von "TensorData" und entsprechende Konstruktoren hat. Möchten Sie eine Antwort ausarbeiten? – metalfox

Antwort

0

Die Aggregat-Initialisierung funktioniert nur für Aggregate, also genau genommen ist das nicht möglich.

Man könnte es entweder emulieren, indem sie ein initializer_list/variadische Vorlage Konstruktor Bereitstellung oder über einen Konstruktor ein Aggregat Version Ihrer Tensor Datenstruktur unter nur für Initialisierungszwecke, so etwas wie:

template <std::size_t r,std::size_t d> 
struct RawTensor 
{ 
    std::array<RawTensor<r-1u,d>,d> data; 
}; 

template <std::size_t d> 
struct RawTensor<0u,d> 
{ 
    double data; 
}; 

template <std::size_t r,std::size_t d> 
struct Tensor 
{ 
    Tensor(RawTensor<r,d> const& data): data_{data}{} 

private: 
    RawTensor<r,d> data_; 
}; 

template <typename... T, 
typename= std::enable_if_t<(std::is_same_v<T,double> && ...) && (sizeof...(T)==9u)>> 
RawTensor<2u,3u> MakeTensor(T... x) { return {x...}; } 

Tensor<2u,3u> t1 = RawTensor<2u,3u>{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }; 
Tensor<2u,3u> t2 = MakeTensor(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); 

und lassen den Compiler optimize es. Wenn Ihre ursprüngliche Absicht darin bestand, die Verkettung von operator [] auszunutzen (und daher verschachtelte Daten vom Tensor-Typ sein müssen), ist dies immer noch möglich, erfordert aber eine weniger triviale Initialisierungslogik.

Verwandte Themen