C++ 中带有 const 参数的 std::variant

Posted

技术标签:

【中文标题】C++ 中带有 const 参数的 std::variant【英文标题】:std::variant with const arguments in C++ 【发布时间】:2021-10-24 11:15:29 【问题描述】:

有一个关于与const 成员联合的很好的未回答问题:Can you write a copy constructor for a union with const members?

其中一个建议是改用std::variant。实际上,必须支持 const 类型 P0086 - Variant design review。相关段落说:

variant<int, const int> 一个variant 可以处理const 类型:他们 只能通过variant构造和emplace()来设置。

所以我假设variant 复制构造也必须支持它们。

但尝试使用此选项:

#include <string>
#include <variant>

using S = std::variant<const int, const std::string>;

int main() 
    S s(1);
    S u = s;

    S v("abc");
    S w = v;

在 GCC 中失败并出现很长的错误(此处仅引用其开头):

n file included from <source>:2:
/opt/compiler-explorer/gcc-trunk-20211024/include/c++/12.0.0/variant: In instantiation of 'constexpr std::__detail::__variant::_Variadic_union<_First, _Rest ...>::_Variadic_union(std::in_place_index_t<_Np>, _Args&& ...) [with long unsigned int _Np = 1; _Args = const int&; _First = const std::__cxx11::basic_string<char>; _Rest = ]':
/opt/compiler-explorer/gcc-trunk-20211024/include/c++/12.0.0/variant:409:4:   required from 'constexpr std::__detail::__variant::_Variadic_union<_First, _Rest ...>::_Variadic_union(std::in_place_index_t<_Np>, _Args&& ...) [with long unsigned int _Np = 2; _Args = const int&; _First = const int; _Rest = const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >]'
/opt/compiler-explorer/gcc-trunk-20211024/include/c++/12.0.0/bits/stl_construct.h:119:7:   required from 'constexpr void std::_Construct(_Tp*, _Args&& ...) [with _Tp = std::__detail::__variant::_Variadic_union<const int, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >; _Args = const std::in_place_index_t<2>&, const int&]'

演示:https://gcc.godbolt.org/z/ocajj3aao

我的代码有问题吗,还是 GCC 必须接受?

【问题讨论】:

问题出现在libstdc++ implemented P2231R1之后,我很怀疑这是个bug。 【参考方案1】:

正如上面评论中提到的,在我实现P2231R1 之后,该代码最近才开始被 GCC 主干拒绝(并且被所有已发布的 GCC 版本接受)。

正如我在bug report 中所说,在 P2231R1 之前,libstdc++ std::variant 在构建工会的活跃成员方面有点快和松散。在 P2231 更改后,我们需要构造正确的联合成员,否则它将在 constexpr 函数中无效。这需要进行一些重构才能在构造成员时使用该成员的索引。

现在已修复,感谢您发现错误。

【讨论】:

以上是关于C++ 中带有 const 参数的 std::variant的主要内容,如果未能解决你的问题,请参考以下文章

c++ 函数:将非 const 参数传递给 const 引用参数

C++ 非 const 右值参数解决方法

将数组作为 C++ 中方法的 const 参数传递

c++重载时const的作用

C++ --- 如果同时定义了两个函数,一个带const,一个不带,会有问题吗?

反应,渲染名称中带有空格的图像的问题