声明后是否可以在constexpr数组中设置元素的值?

时间:2017-04-04 11:08:19

标签: c++ arrays c++11 constexpr

是否可以在一个点声明一个const数组(可能是constexpr),然后在另一个地方定义它,一次一个元素?

E.g。

extern constexpr int myArray[100];


myArray[0] = myConstexprFunction(0);
myArray[1] = myConstexprFunction(1);
// ...
myArray[100] = myConstexprFunction(100);

我想做的事情需要这样的事情。也许可以使用以下内容:http://b.atch.se/posts/constexpr-counter/

但是如果这种技术在下一个C ++标准中是非法的(我希望不是),我想使用更安全的技术。

[编辑]如何放宽一些要求..让我们说我想做这样的事情:

constexpr int myConstExprFunction(int arg) { return arg + 100;}
// other code...
constexpr int a = myConstExprFunctionBegin(10);
constexpr int b = myConstExprFunction(20);
constexpr int c = myConstExprFunction(30);
constexpr int d = myConstExprFunctionEnd(40);

我想要的是myConstExprFunctionEnd能够使用前面函数创建的值生成最终数组。 一切都在编译时。当然。

[EDIT2]非常欢迎C ++ 11解决方案

5 个答案:

答案 0 :(得分:4)

constexpr声明可以在编译时评估函数或变量的值。

所以你可以将它与数组一起使用的唯一方法就是:

constexpr int myArray[100]{1 , 2 , 3 ,.........};

等语句

myArray[0] = myConstexprFunction(0);

只能在运行时进行评估。所以它不可能。

答案 1 :(得分:4)

最近的C ++ constexpr的要求非常宽松,所以你可以写一下:

// requires C++17:
constexpr auto myArray = [] {
    std::array<int, 100> result {};
    for (size_t i = 0; i < 100; ++ i) {
        result[i] = i * i;
    }
    return result;
}();

注意我使用了std::array<int, 100>而不是int[100],因为函数无法返回C数组。

以上代码需要C ++ 17,原因有两个:

  1. constexpr lambda
  2. 在{+ C ++ 17
  3. 之前,mutable operator[]不是constexpr

    使用单独的constexpr函数可以轻松解决问题1。问题2只能通过定义自己的数组包装器来解决。

    // requires C++14:
    
    template <typename T, size_t n>
    struct ConstexprArray {
        T data[n];
        constexpr ConstexprArray() : data{} {}
        constexpr T& operator[](size_t i) { return data[i]; }
    };
    
    constexpr auto initialize_my_array() -> ConstexprArray<int, 100> {
        ConstexprArray<int, 100> result {};
        for (size_t i = 0; i < 100; ++ i) {
            result[i] = i * i;
        }
        return result;
    }
    
    constexpr auto myArray = initialize_my_array();
    

答案 2 :(得分:3)

如果你想声明constexpr一个数组并使用constexpr函数初始化它的值......我能想到的最好的方法是将数组包装在struct / array中并通过委托初始化它构造

以下是一个完整的C ++ 14示例

#include <utility>
#include <iostream>

constexpr int myConstexprFunction (int i)
 { return i << 1; } // return 2*i

template <std::size_t S>
struct wrapArray
 {
   int const myWrappedArray[S];

   template <int ... Is>
   constexpr wrapArray (std::integer_sequence<int, Is...> const &)
      : myWrappedArray { myConstexprFunction(Is)... }
    { }

   constexpr wrapArray ()
      : wrapArray(std::make_integer_sequence<int, S>())
    { }
 };


int main ()
 {
   constexpr wrapArray<100>  wa100;

   for ( auto i : wa100.myWrappedArray )
      std::cout << i << ", ";

   std::cout << std::endl;
 }

如果您需要C ++ 11代码,则必须替换std::integer_sequencestd::make_integer_sequence()。这并不难。

答案 3 :(得分:3)

查看您的编辑,我只回答 no ,因为编译器无法将一组变量转换为数组。它只是不那样工作。在C ++中没有任何构造可以采取一堆声明,删除它们并用另一个声明替换它。源代码预处理器或生成器可能能够允许您寻找的语法。

如果您对不需要外部工具的解决方案感兴趣,可以创建一个返回数组的constexpr函数:

constexpr auto makeMyArray() {
    std::array<int, 100> myArray;

    myArray[0] = myConstExprFunction(10);
    myArray[1] = myConstExprFunction(20);
    // ...

    return myArray;
}

然后,初始化你的数组:

constexpr auto myArray = makeMyArray();

答案 4 :(得分:1)