使用constexpr初始化数组?

7

我想知道是否可以使用C++ 2011的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));
}

有没有一种方法可以使用constexpr初始化myVar,而不需要手动填充数组?如果存在这样的方法,给定示例的语法将是什么?
为了更清楚地表达问题,我正在寻找一种使用单个函数调用填充myVar所有值的方法。

如何使用初始化列表:(https://dev59.com/4UfRa4cB1Zd3GeqP_rkM) - fileoffset
2
“without filling the array manually”是什么意思?此外,在这里您不需要使用constexpr。如果您正在设置_myVar的维度,则需要使用它。 - juanchopanza
@juanchopanza:我认为问题是:如何以通用的方式使用constexpr函数填充constexpr数组? - mirk
已经有一个不错的基于模板的解决方案讨论过。但是,这取决于编译器的模板递归深度限制。如果达到了限制,请使用Boost预处理库,特别是BOOST_PP_ENUM :-) - Andreas Spindler
1个回答

3
没有看到 MyClass 的定义,问题还不够清晰。我认为你想要初始化 MyClass::_myVar,而不是用迭代的方式填充它,这是正确的吧。
你的代码表明 MyClass::_myVar 是一个静态类成员。在这种情况下,你对成员的初始化是符合 C++11 标准的。以下程序演示了这一点(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;
}

这让我倾向于认为MyClass::_myVar不是静态成员——尽管我不确定为什么这个整数常量数组不是静态的。如果是这样的话,那么你可以使用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];
};

在两种情况下,metaFunctionconstexpr 属性实际上并不是编译所必需的。如果将 constexpr 删除,则 /* MyClass Version 1*/ 对于 C++03 也是可行的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接