我试图写一个非常简单的变体和访问者实现,如下所示,但我遇到了编译错误,我不知道为什么。
#include <variant>
#include <string>
#include <iostream>
struct foo
{
std::string s;
};
struct bar
{
double s;
};
using var = std::variant<foo, bar>;
struct visitor
{
template <class T>
auto operator()(const T v) -> decltype(v.s)
{
return v.s;
}
};
int main()
{
foo f;
f.s = 3.0;
var x = f;
auto xs = std::visit(visitor{}, x);
std::cout<<xs<<std::endl;
}
这个错误太长了,太复杂了,让我作为一个c++11+的新手感到困惑
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/variant: In instantiation of 'static constexpr auto std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Rest ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {1}]':
/usr/local/include/c++/8.1.0/variant:825:61: required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_single_alt(_Tp&) [with long unsigned int __index = 1; _Tp = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&)> _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}]'
/usr/local/include/c++/8.1.0/variant:813:39: required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_all_alts(std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type&, std::index_sequence<__indices ...>) [with long unsigned int ...__var_indices = {0, 1}; _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}; std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2> std::index_sequence<__indices ...> = std::integer_sequence<long unsigned int, 0, 1>]'
/usr/local/include/c++/8.1.0/variant:803:19: required from 'static constexpr std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}; std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2>]'
/usr/local/include/c++/8.1.0/variant:863:38: required from 'static constexpr std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_Array_type std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; _Variants = {std::variant<foo, bar>&}; std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2>]'
/usr/local/include/c++/8.1.0/variant:866:49: required from 'constexpr const std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2> std::__detail::__variant::__gen_vtable<std::__cxx11::basic_string<char>, visitor&&, std::variant<foo, bar>&>::_S_vtable'
/usr/local/include/c++/8.1.0/variant:866:29: required from 'struct std::__detail::__variant::__gen_vtable<std::__cxx11::basic_string<char>, visitor&&, std::variant<foo, bar>&>'
/usr/local/include/c++/8.1.0/variant:1394:23: required from 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = visitor; _Variants = {std::variant<foo, bar>&}]'
main.cpp:34:38: required from here
/usr/local/include/c++/8.1.0/variant:848:43: error: invalid conversion from 'std::__success_type<double>::type (*)(visitor&&, std::variant<foo, bar>&)' {aka 'double (*)(visitor&&, std::variant<foo, bar>&)'} to 'std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&)' [-fpermissive]
{ return _Array_type{&__visit_invoke}; }
std::visit要求返回类型与所有组合的值类别相同:
返回类型是从返回的表达式中推导出来的,就像通过decltype一样。对于所有变体的替代类型的所有组合,如果上面的调用不是同一类型和值类别的有效表达式,则调用格式错误。
参见C++标准草案[variant.visit]p2:
要求:对于每个有效的包m,e(m(应是一个有效的表达式。所有此类表达应具有相同的类型和价值类别;否则,该程序就是格式错误的。
例如,如果每个结构都有一个int成员x,而您返回它将不再是格式错误的,请参阅godbolt。在您的情况下,您可以将访问者更改为简单打印,而不是返回值see it live:
struct visitor
{
template <class T>
void operator()(const T v)
{
std::cout<< v.s;
}
};