The following code
#include <optional>
#include <string>
#include <variant>
constexpr bool USE_VARIANT = 1;
using T = std::conditional_t<USE_VARIANT, std::variant<std::string>, std::string>;
struct S
{
T t;
};
constexpr int func()
{
S s{"str"};
return 0;
}
constexpr int x = func();
int main()
{
}
fails to compile with GCC trunk (compiler explorer link) with the message
In file included from <source>:4:
<source>:21:23: in 'constexpr' expansion of 'func()'
<source>:19:1: in 'constexpr' expansion of '(& s)->S::~S()'
<source>:10:8: in 'constexpr' expansion of '((S*)this)->S::t.std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~variant()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:1408:28: in 'constexpr' expansion of '((std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Variant_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~_Variant_base()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:736:12: in 'constexpr' expansion of '((std::__detail::__variant::_Variant_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::__detail::__variant::_Variant_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Move_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~_Move_assign_base()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:682:12: in 'constexpr' expansion of '((std::__detail::__variant::_Move_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::__detail::__variant::_Move_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Copy_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~_Copy_assign_base()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:630:12: in 'constexpr' expansion of '((std::__detail::__variant::_Copy_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::__detail::__variant::_Copy_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Move_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~_Move_ctor_base()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:592:12: in 'constexpr' expansion of '((std::__detail::__variant::_Move_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::__detail::__variant::_Move_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Copy_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~_Copy_ctor_base()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:555:12: in 'constexpr' expansion of '((std::__detail::__variant::_Copy_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::__detail::__variant::_Copy_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Variant_storage<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~_Variant_storage()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:481:17: in 'constexpr' expansion of '((std::__detail::__variant::_Variant_storage<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->std::__detail::__variant::_Variant_storage<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::_M_reset()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:471:23: in 'constexpr' expansion of 'std::__do_visit<void, __detail::__variant::_Variant_storage<false, __cxx11::basic_string<char, char_traits<char>, allocator<char> > >::_M_reset()::<lambda(auto:11&&)>, variant<__cxx11::basic_string<char, char_traits<char>, allocator<char> > >&>(<lambda closure object>std::__detail::__variant::_Variant_storage<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::_M_reset()::<lambda(auto:11&&)>(), (* & std::__variant_cast<__cxx11::basic_string<char, char_traits<char>, allocator<char> >, __detail::__variant::_Variant_storage<false, __cxx11::basic_string<char, char_traits<char>, allocator<char> > >&>((*(std::__detail::__variant::_Variant_storage<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this))))'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:1782:26: in 'constexpr' expansion of '(& __v0)->std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::index()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:555:12: error: accessing value of 's.S::t.std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Variant_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Move_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Copy_assign_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Move_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>.std::__detail::__variant::_Copy_ctor_base<false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<anonymous>' through a 'const std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' glvalue in a constant expression
555 | struct _Copy_ctor_base : _Variant_storage_alias<_Types...>
| ^~~~~~~~~~~~~~~
C++ errors are often difficult to understand, but this one just left me clueless.
If I use USE_VARIANT = 0
, it compiles.
If I change it to
constexpr int func()
{
T t{"str"};
return 0;
}
it compiles with either value.
With
constexpr int func()
{
std::optional<T> t{"str"};
return 0;
}
it doesn't compile either.
So it seems that when a std::variant<..., std::string, ...>
is instantiated in a class, it fails to compile. The same happens with a std::vector<char>
instead of a std::string
, but other classes (that don't allocate memory dynamically) seem to work fine.
Am I missing something or have I found a compiler/stdlib bug?
constexpr
string, I think this is a libstdc++ bug. – Makedamakefast