std::variant 在 C++ 中使用 const 参数
std::variant with const arguments in C++
有一个关于与 const
成员联合的很好的未回答问题:
其中一个建议是改用 std::variant
。事实上,必须支持 const 类型 P0086 - Variant design review。相关段落说:
variant<int, const int>
A variant
can handle const
types: they
can only be set through variant
construction and 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 必须接受它?
如上面评论所述,在我实施 P2231R1.
之后,代码最近才开始被 GCC 主干拒绝(并被所有发布的 GCC 版本接受)
正如我在 bug report 中所说,在 P2231R1 之前,libstdc++ std::variant
在构建联合会的活跃成员方面玩得有点快和松散。 P2231 改变后,我们需要构造正确的联合成员,否则它将在 constexpr
函数中无效。这需要一些重构才能在构造成员时使用成员的索引。
现在已经修复,感谢您注意到这个错误。
有一个关于与 const
成员联合的很好的未回答问题:
其中一个建议是改用 std::variant
。事实上,必须支持 const 类型 P0086 - Variant design review。相关段落说:
variant<int, const int>
Avariant
can handleconst
types: they can only be set throughvariant
construction andemplace()
.
所以我假设 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 必须接受它?
如上面评论所述,在我实施 P2231R1.
之后,代码最近才开始被 GCC 主干拒绝(并被所有发布的 GCC 版本接受)正如我在 bug report 中所说,在 P2231R1 之前,libstdc++ std::variant
在构建联合会的活跃成员方面玩得有点快和松散。 P2231 改变后,我们需要构造正确的联合成员,否则它将在 constexpr
函数中无效。这需要一些重构才能在构造成员时使用成员的索引。
现在已经修复,感谢您注意到这个错误。