The following code was tested on most clang and GCC compilers available on Godbolt, and my local machine running Arch Linux, gcc (GCC) 9.2.0. Starting from GCC version 9, the following code results in a compile-time error: "modification of '<temporary>' is not a constant expression" on the line with the closing brace of the initializer_list initialization. Code on Godbolt (has some extras compared to the minimal version below): https://godbolt.org/z/baRg-1 // start of source code #include <string_view> #include <initializer_list> struct S { const int i; }; constexpr std::initializer_list<S> foo{ { []() { return std::string_view("").compare(""); }() } }; // end of source code Another version I tested with used a constexpr function rather than a lambda, with the same failing result. I have also tried replacing the lambda body with a simple "return true;" which fixes the error.
Changed in r261086.
I started getting the same error after upgrading to GCC 9.3.0. The problem in my case is either related to the use of std::pair in constexpr or the fact that I have nested instances of std::initializer_list. The workaround was to replace std::pair with a custom struct as seen here: struct zone_name_root_variant_type { const char *name; std::initializer_list<ZONE_NAME_AFFIX> affixes; }; struct zone_name_root_type { ZONE_NAME_ROOT index; const char *region; std::initializer_list< zone_name_root_variant_type /* std::pair< const char*, std::initializer_list<ZONE_NAME_AFFIX> > */ > variants; }; static constexpr const zone_name_root_type zone_name_root_table[] = { { ZONE_NAME_ROOT::UNKNOWN, "Region", { { "", { ZONE_NAME_AFFIX::UNKNOWN } } } }, { ZONE_NAME_ROOT::NONE, "", { } } };
I also found out that when I try to populate a constexpr array using a trivial constexpr function that passes on the argument initializer list then I get the same error. This does not work any more within the definition of a constexpr array: constexpr room_desc_part_type make( ROOM_DESC_PART part, std::initializer_list<const char *> args ) { return #if __cplusplus <= 201703L __extension__ #endif // __cplusplus room_desc_part_type{ .index = part, .arguments = args }; }
Looks like this is fixed for GCC 12.3+ by the fix for PR107079.