2012-05-10 4 views
7

Ich frage mich, ob es möglich ist, ein ganzes Array mit einer constexpr-Funktion zu initialisieren (mit C++ 2011). Hier habe ich etwas zu zeigen, was ich tun möchte:Initialisierung eines Arrays mit einem Constexpr?

template<unsigned int DIM> const unsigned int MyClass<DIM>::_myVar[2][3] = { 
{metaFunction(0, 0, DIM), metaFunction(0, 1, DIM), metaFunction(0, 2, DIM)}, 
{metaFunction(1, 0, DIM), metaFunction(1, 1, DIM), metaFunction(1, 2, DIM)} 
}; 

template<unsigned int DIM> inline constexpr unsigned int MyClass<DIM>::metaFunction(const unsigned int k, const unsigned int n, const unsigned int dim) 
{ 
    return (((n < dim) && (k < n)) ? (1<<(n-k)) : (0)); 
} 

Gibt es eine Möglichkeit meineVar mit einem constexpr zu initialisieren, ohne manuell das Array zu füllen. Und wenn es existiert, wie wäre die Syntax für das gegebene Beispiel?

Um die Frage ein wenig zu präzisieren, suche ich nach einer Möglichkeit, alle Werte von myVar mit einem einzigen Funktionsaufruf zu füllen.

+0

Wie wäre es mit einer Initialisierungsliste: (http://stackoverflow.com/questions/907471/c0x-initializer-list-example) – fileoffset

+2

Was meinen Sie mit "ohne das Array manuell zu füllen"? Außerdem brauchen Sie hier keinen 'constexpr'. Sie würden, wenn Sie die Dimensionen von _myVar festlegen würden. – juanchopanza

+0

@juanchopanza: Ich denke, die Frage ist: Wie füllt man ein consExpr-Array mit constexpr-Funktionen in einer generischen Art und Weise? – mirk

Antwort

3

Ohne die Definition von MyClass zu sehen, ist das Problem nicht ganz klar. Ich glaube sowieso, dass Sie MyClass::_myVar initialisiert werden möchten ohne Code, um es iterativ mit den Werten MyClass::metaFunction() zu füllen.

Ihr Code schlägt vor, dass MyClass::_myVar ein statisches Klassenmitglied ist. In diesem Fall Fall ist Ihre Initialisierung des Mitglieds C++ 11 in einwandfreiem Zustand. Das folgende Programm veranschaulicht (GCC 4.6.3):

#include <iostream> 

/* MyClass Version 1 */ 
template<unsigned int DIM> 
struct MyClass 
{ 
    static constexpr unsigned int metaFunction(
     const unsigned int k, 
     const unsigned int n, 
     const unsigned int dim); 

    static const unsigned int _myVar[2][3]; 
}; 

template<unsigned int DIM> inline constexpr 
unsigned int MyClass<DIM>::metaFunction(
    const unsigned int k, 
    const unsigned int n, 
    const unsigned int dim) 
{ 
    return (((n < dim) && (k < n)) ? (1<<(n-k)) : (0)); 
} 

template<unsigned int DIM> const unsigned int MyClass<DIM>::_myVar[2][3] = { 
    { metaFunction(0, 0, DIM), 
     metaFunction(0, 1, DIM), 
     metaFunction(0, 2, DIM) 
    }, 
    { metaFunction(1, 0, DIM), 
     metaFunction(1, 1, DIM), 
     metaFunction(1, 2, DIM) 
    } 
}; 

template<unsigned int DIM> inline constexpr 
unsigned int MyClass<DIM>::metaFunction(
    const unsigned int k, 
    const unsigned int n, 
    const unsigned int dim) 
{ 
    return (((n < dim) && (k < n)) ? (1<<(n-k)) : (0)); 
} 

using namespace std; 

int main(void) 
{ 
    MyClass<3> mine; 
    for (int i = 0; i < 2; ++i) { 
     for (int j = 0; j < 3; ++j) { 
      cout << mine._myVar[i][j] << endl; 
     } 
    } 
    return 0; 
} 

Das bin ich geneigt zu glauben, dass MyClass::_myVar ist nicht ein statisches Element - obwohl warum dieses Array von Integer-Konstanten nicht statisch sein würde ich nicht sicher bin, . Wenn das der Fall ist, dann können Sie das Element in der uniform initialization provision of C++11 mit Standard Konstruktor initialisieren:

/* MyClass Version 2 */ 
template<unsigned int DIM> 
struct MyClass 
{ 
    MyClass() 
    : _myVar{ 
      { MyClass::metaFunction(0, 0, DIM), 
       MyClass::metaFunction(0, 1, DIM), 
       MyClass::metaFunction(0, 2, DIM) 
      }, 
      { MyClass::metaFunction(1, 0, DIM), 
       MyClass::metaFunction(1, 1, DIM), 
       MyClass::metaFunction(1, 2, DIM) 
      } 
    }{} 

    static constexpr unsigned int metaFunction(
     const unsigned int k, 
     const unsigned int n, 
     const unsigned int dim); 

    const unsigned int _myVar[2][3]; 
}; 

In keinem Fall ist die constexpr Attribut metaFunction tatsächlich notwendig für die Kompilierung. Und wenn constexpr entfernt wird, dann ist /* MyClass Version 1*/ auch gut für C++ 03.