7

I wonder if it is possible to initialize an entire array with a constexpr function (with C++ 2011). Here I have something to illustrate what I want to do :

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));
}

Is there a way to initialize myVar with a constexpr without filling the array manually. And if it exists, what would be the syntax for the given example ?

To precise the question a little, I search for a way to fill all values of myVar using a single function call.

Mat
  • 202,337
  • 40
  • 393
  • 406
Vincent
  • 57,703
  • 61
  • 205
  • 388
  • How about an initializer list: (http://stackoverflow.com/questions/907471/c0x-initializer-list-example) – fileoffset May 10 '12 at 06:56
  • 2
    What do you mean by "without filling the array manually"? Also, you don't need a `constexpr` here. You would if you were setting the dimensions of `_myVar`. – juanchopanza May 10 '12 at 07:37
  • @juanchopanza: I think the question is: How to fill a constexpr array using constexpr functions in a generic way? – mirk May 10 '12 at 08:12
  • I nice, template-based solution has been already [discussed](http://stackoverflow.com/questions/2978259/programmatically-create-static-arrays-at-compile-time-in-c). However, this depends on the template recursion depth of your compiler. If the limit is reached use the [Boost Preprocessor Library](http://www.boost.org/doc/libs/1_49_0/libs/preprocessor/doc/index.html), in particular [`BOOST_PP_ENUM`](http://stackoverflow.com/questions/9531645/array-of-2s-power-using-template-in-c) :-) – Andreas Spindler May 10 '12 at 10:39

1 Answers1

3

Without seeing the definition of MyClass the problem is not quite clear. I believe anyway that you want to get MyClass::_myVar initialized without code to iteratively fill it with the MyClass::metaFunction() values.

You code suggests that MyClass::_myVar is a static class member. In that case your initialization of the member is perfectly good C++11 as it stands. The following program illustrates (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;
}

This inclines me to think that MyClass::_myVar is not a static member - although why this array of integer constants would not be static I am not sure. If that is the case, then you can initialize the member in the default constructor using the 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];
};

In neither case is the constexpr attribute of metaFunction actually necessary for compilation. And if constexpr is removed then /* MyClass Version 1*/ is also good for C++03.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182