【问题标题】:std::variant of std::string inside any class in constexpr context fails to compileconstexpr 上下文中任何类中的 std::string 的 std::variant 无法编译
【发布时间】:2021-12-31 11:05:40
【问题描述】:

以下代码

#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()
{
}

使用 GCC 中继 (compiler explorer link) 编译失败并显示消息

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++ 错误通常很难理解,但这个让我一头雾水。

如果我使用USE_VARIANT = 0,它会编译。

如果我把它改成

constexpr int func()
{
    T t{"str"};
    return 0;
}

它使用任一值编译。

constexpr int func()
{
    std::optional<T> t{"str"};
    return 0;
}

它也不编译。

因此,当std::variant&lt;..., std::string, ...&gt; 在类中实例化时,它似乎无法编译。 std::vector&lt;char&gt; 而不是 std::string 也会发生同样的情况,但其他类(不动态分配内存)似乎工作正常。

是我遗漏了什么还是发现了编译器/stdlib 错误?

【问题讨论】:

  • @cigien GCC does support constexpr strings,至少在后备箱上。这就是我一直在使用的。
  • @cigien。 GCC-trunk 已经实现了constexpr 字符串,我认为这是一个libstdc++ 的bug。
  • 哦,你们都是对的。我的错,那么请忽略我之前的评论,'
  • Bug 103879 归档。

标签: c++ gcc c++20 constexpr std-variant


【解决方案1】:

错误是fixed,现在可以编译示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    相关资源
    最近更新 更多