0

I have an array called foos with instances of Foo. They are stored in an std.array and I would like to initialize them during compile time. Is that possible by using C++17 and 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++);
    }
}

It seems the initialization is still done during runtime. Am I missing something?

https://gcc.godbolt.org/z/r4WUbE

I am aware that -O3 will generate better output, but my original example is slightly better and the compiler does not optimize it under this optimization.

1 Answer 1

1

constexpr doesn’t mean “schedule this function to run before (normal) execution begins”. In particular, a constant expression cannot modify an object (here, any of the Foo::_a objects) that it did not create. You can, however, make a constexpr function that returns an array and use it as an initializer:

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();
Sign up to request clarification or add additional context in comments.

6 Comments

Shouldn’t it be static constexpr Foos foos=iota_foos(); to enforce that iota_foos is evaluated in a constexpr context?
@JonasGreitemann: There was no statement that foos should be const. It’s constant-initialized anyway (but cannot itself be used in constant expressions); C++20 provides constinit to verify that fact without changing the type.
Agreed. Upon testing, I checked that gcc and clang constant-initialized it even at -O0, but as it stands, there's no way to guarantee this pre-C++20. However, if foos were const, it really should be constexpr. As pointed out by Jason Turner at CppCon, static const is a code smell.
@JonasGreitemann: We can guarantee that iota_foos is called at compile time and just have no guaranty about copy constructor: static constexpr Foos const_foos=iota_foos(); static Foos foos= const_foos();.
@JonasGreitemann: Constant initialization isn’t an optimization; it’s just part of the language. So it is guaranteed, but absent constexpr/constinit there’s no way to “guarantee the guarantee”.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.