2012-05-10 22 views
7

Me pregunto si es posible inicializar una matriz completa con una función constexpr (con C++ 2011). Aquí tengo algo para ilustrar lo que quiero hacer:Inicializando una matriz con un 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)); 
} 

¿Hay una manera de inicializar miVar con un constexpr sin llenar la matriz de forma manual. Y si existe, ¿cuál sería la sintaxis para el ejemplo dado?

Para precisar un poco la pregunta, busco la forma de llenar todos los valores de myVar con una sola llamada de función.

+0

¿Qué tal una lista de inicializadores: (http://stackoverflow.com/questions/907471/c0x-initializer-list-example) – fileoffset

+2

¿Qué quiere decir con "sin llenar la matriz manualmente"? Además, no necesitas un 'constexpr' aquí. Lo haría si estuviera configurando las dimensiones de '_myVar'. – juanchopanza

+0

@juanchopanza: Creo que la pregunta es: ¿cómo llenar un conjunto de constexpr utilizando funciones de constexpr de una manera genérica? – mirk

Respuesta

3

Sin ver la definición de MyClass, el problema no está del todo claro. Creo que de todos modos que desea obtener MyClass::_myVar inicializado sin código para llenarlo iterativamente con los valores MyClass::metaFunction().

Su código sugiere que MyClass::_myVar es un miembro de clase estático. En ese caso su inicialización del miembro es perfectamente buena C++ 11 tal como está. El siguiente programa ilustra (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; 
} 

Esto me inclina a pensar que es MyClass::_myVarno un miembro estático - aunque por qué este conjunto de constantes enteras no sería estática No estoy seguro . Si ese es el caso, entonces se puede inicializar el miembro en el constructor por defecto utilizando el uniform initialization provision of C++11:

/* 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]; 
}; 

En ninguno de los casos es el atributo de constexprmetaFunction realidad necesaria para la compilación. Y si se elimina constexpr entonces /* MyClass Version 1*/ también es bueno para C++ 03.