C++ 使用constexpr初始化std.array中的对象

C++ 使用constexpr初始化std.array中的对象,c++,c++17,constexpr,C++,C++17,Constexpr,我有一个名为foos的数组,其中包含Foo的实例。它们存储在std.array中,我想在编译时初始化它们。使用C++17和constexpr是否可以实现这一点 struct Foo { constexpr void setA(int a); int _a{0}; }; static std::array<Foo, 100> foos; static constexpr void initialize() { int i = 0; for (auto

我有一个名为
foos
的数组,其中包含
Foo
的实例。它们存储在std.array中,我想在编译时初始化它们。使用
C++17
和constexpr是否可以实现这一点

struct Foo
{
    constexpr void setA(int a);
    int _a{0};
};

static std::array<Foo, 100> foos;

static constexpr void initialize()
{
    int i = 0;
    for (auto& e : foos)
    {
        e.setA(i++);
    }
}
structfoo
{
constexpr void setA(int a);
int_a{0};
};
静态std::数组foos;
静态constexpr void initialize()
{
int i=0;
适用于(自动和电气:foos)
{
e、 setA(i++);
}
}
似乎初始化仍在运行时完成。我错过什么了吗


我知道
-O3
将生成更好的输出,但我的原始示例稍微好一点,编译器不会在这种优化下对其进行优化。

constepr
并不意味着“将此函数安排在(正常)执行开始之前运行”。特别是,常量表达式不能修改它没有创建的对象(这里是任何
Foo::_a
对象)。但是,您可以创建一个
constepr
函数,该函数返回一个
数组
,并将其用作初始值设定项

using Foos=std::array<Foo,100>;
constexpr Foos iota_foos() {
  Foos ret;
  int i=0;
  for(auto &f : ret) f.setA(i++);
  return ret;
}

static Foos foos=iota_foos();
使用Foos=std::array;
constexpr Foos iota_Foos(){
Foos ret;
int i=0;
for(auto&f:ret)f.setA(i++);
返回ret;
}
静态Foos Foos=iota_Foos();

它不应该是
静态constexpr Foos Foos=iota_Foos()
要强制执行在constexpr上下文中对
iota\u foos
进行评估?@jonasgreeitemann:没有声明
foos
应为
const
。它仍然是初始化的常量(但不能在常量表达式中使用);C++20提供了
continit
来验证该事实,而无需更改类型。同意。在测试时,我检查了gcc和clangconstant是否在
-O0
处对其进行了初始化,但就目前情况而言,无法保证这是C++20之前的版本。然而,如果
foos
const
,那么它实际上应该是
constepr
。正如CppCon的Jason Turner所指出的,
static const
是一种代码气味。@Jonasgreeitemann:我们可以保证
iota\u foos
在编译时被调用,只是对复制构造函数没有任何保证:
static constexpr foos const\u foos=iota\u foos();静态Foos Foos=const_Foos()
@jonasgreeitemann:常量初始化不是优化;这只是语言的一部分。因此它是有保证的,但如果没有
constexpr
/
constinit
就没有办法“保证保证”。