【问题标题】:Is it possible to initialize constexpr std::array member in a programtic way是否可以以编程方式初始化 constexpr std::array 成员
【发布时间】:2018-05-09 23:12:27
【问题描述】:

假设我想编写一个结构体,它的成员 constexpr std::array 包含前 N 个 fib,其中 N 是模板参数。

类似这样的东西,但 vals 在编译时可用:

template <int N>
struct first_n_fibs {
    static_assert(N>0);
    static const std::array<int, N> vals;
    static std::array<int, N> init_fibs(){
        std::array<int,N> result;
        if (N==1) {
            return std::array<int,N>{1};
        } else {
            result[0]=1;
            result[1]=1;
            for(int i =2; i<N;++i) {
                result[i]=result[i-2]+result[i-1];
            }
        }
        return result;
    }
};

template<int N>
const std::array<int, N> first_n_fibs<N>::vals=init_fibs();


int main(){
    std::cout << first_n_fibs<2>::vals.back() << std::endl;
    std::cout << first_n_fibs<5>::vals.back() << std::endl;
    std::cout << first_n_fibs<6>::vals.back() << std::endl;
}

我怀疑没有解决方法,因为 std::array 构造函数不是 constexpr,所以如果有人知道任何涉及 C 数组或 boost 的解决方法,我会很高兴的。

【问题讨论】:

  • 我想知道你为什么希望它是std::array。此外,first_n_fibs&lt;n&gt; 创建了很多实例,而所有这些(前缀)都相等。
  • 因为IDK如何在编译时对C数组进行操作。至于实例和重复:我知道,但在某些情况下,这是值得的。
  • 如果你在 C 数组上工作,那么任何前缀相等的 const first_n_fibs 都可以用指向最长数组的单个指针来表示。你能提供你的用例吗?
  • 否则,如果您只想在编译时获取 nth-fib,则 std::array 可能是矫枉过正。

标签: c++ constexpr stdarray


【解决方案1】:

你不需要什么特别的,constexpr这几天功能要求很宽松:

#include <iostream>
#include <array>

template <int N> constexpr std::array<int, N> first_n_fibs()
{
    std::array<int, N> ret{};
    ret[0] = 0;
    if (N == 1) return ret;
    ret[1] = 1;
    for (int i = 2; i < N; i++)
        ret[i] = ret[i-2] + ret[i-1];
    return ret;
}

int main()
{
    constexpr auto a = first_n_fibs<3>();
}

(try it live)


std::array 构造函数不是 constexpr

显然它有no user-defined constructors at all,所以没有什么能阻止它的构造是constexpr

【讨论】:

  • 不错的解决方法,但总的来说我更喜欢在课堂上使用它,因为从设计的角度来看,拥有一堆“getter”函数并不好(而且可能更慢)。
  • 其实你是对的,gcc 给了我蹩脚的错误,我所做的只是我没有像你那样使用 {} 初始化 ret。
【解决方案2】:

你可以使用立即调用的 lambda:

struct foo {
    static constexpr auto arr = []{
        std::array<int, 6> a{};

        for (auto& e : a) {
            // stuff
        }

        return a;
    }();
};

但正如 HolyBlackCat 所说,std::array 是 constexpr 可构造的,因为它没有定义的构造函数,只有编译器定义的构造函数。

这里是live example at coliru

【讨论】:

  • "std::array is fully constexpr constructible" IDK 语言术语,但是当我将 constexpr 放在 member 前面时,它不会编译 :)
  • "错误:constexpr 静态数据成员 'vals' 必须有一个初始化程序"
  • @NoSenseEtAl 在创建变量 constexpr 时,您必须给它一个值,正如您的编译器告诉您的那样。它需要一个初始化程序。或者,您可以将定义内联并标记定义添加 constexpr。
  • 请看我的其他 cmets,错误是我在函数中初始化数组时没有写 {},而 GCC 给了我愚蠢的错误。
  • 我仍然赞成你的回答,很抱歉你浪费时间帮助我,但真正的错误闻起来像 constexpr 问题(它包含“不能用作 constexpr 函数,因为”)
猜你喜欢
  • 2021-04-18
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多