I have some problems with aggregate initialization of a union containing std::string
evaluated in constant expression. This example program demonstrates it:
constexpr bool f() {
union U{
std::string s;
constexpr ~U(){ s.~basic_string(); }
} u{};
return true;
}
static_assert( f() );
I assume that u{}
shall set std::string s;
as active union member and default initialize it. And indeed it work in MSVC and in Clang with libc++
. But in Clang with libstdc++
or in GCC it produces the error:
error: non-constant condition for static assertion
in 'constexpr' expansion of 'f()'
in 'constexpr' expansion of '(& u)->f()::U::~U()'
in 'constexpr' expansion of '((f()::U*)this)->f()::U::s.std::__cxx11::basic_string<char>::~basic_string()'
/opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/basic_string.h:803:19: in 'constexpr' expansion of '((std::__cxx11::basic_string<char>*)this)->std::__cxx11::basic_string<char>::_M_dispose()'
error: accessing 'std::__cxx11::basic_string<char>::<unnamed union>::_M_allocated_capacity' member instead of initialized 'std::__cxx11::basic_string<char>::<unnamed union>::_M_local_buf' member in constant expression
Online demo: https://gcc.godbolt.org/z/bbf4Yo3v9
The error in GCC can be eliminated by adding default initializer to
std::string s{};
by Clang still prints the error:
: error: static assertion expression is not an integral constant expression
include/c++/12.2.0/bits/basic_string.h:356:10: note: assignment to member '_M_local_buf' of union with no active member is not allowed in a constant expression
__c = _CharT();
^
include/c++/12.2.0/bits/basic_string.h:519:2: note: in call to '&u.s->_M_use_local_data()'
_M_use_local_data();
^
note: in call to 'basic_string()'
std::string s{};
^
Online demo: https://gcc.godbolt.org/z/q84vcMTef
Is it just an issue with libstdc++
or the program is ill formed?