I encountered an issue where I need to use std::visit()
on two std::variant
objects which are guaranteed to host the same type at the time of the call. The following code compiles without issues:
std::variant<int, float> var1 = get_variant();
std::variant<int, float> var2 = get_variant();
std::visit([](auto val1, decltype(val1) val2) {
// ...
var1, var2);
However, I want to do the same with references and it seems that I can't. The following code does not compile:
std::visit([](auto&& rref1, decltype(rref1) rref2) {
// ...
}, var1, var2);
I am not using auto
for both arguments to force the compiler to only generate two instances of the lambda with argument types: (int, int)
, (double, double)
. In my actual program, the variants have 10 types and I would prefer that only 10 functions are generated instead of all possible combinations which is 10^2 = 100.
I am surprised that the second snippet does not compile, can anyone tell me why?
Edit - Compiler Output (gcc 9.4)
These are the first few lines of errors:
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant: In instantiation of ‘static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::__visit_invoke_impl(_Visitor&&, _Variants ...) [with bool __same_return_types = true; _Result_type = void; _Visitor = main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&; _Variants = {std::variant<int, float>&, std::variant<int, float>&}; long unsigned int ...__indices = {0, 1}]’:
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant:989:28: required from ‘static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::__do_visit_invoke(_Visitor&&, _Variants ...) [with bool __same_return_types = true; _Result_type = void; _Visitor = main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&; _Variants = {std::variant<int, float>&, std::variant<int, float>&}; long unsigned int ...__indices = {0, 1}]’
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant:1005:28: required from ‘static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::__visit_invoke(_Visitor&&, _Variants ...) [with bool __same_return_types = true; _Result_type = void; _Visitor = main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&; _Variants = {std::variant<int, float>&, std::variant<int, float>&}; long unsigned int ...__indices = {0, 1}]’
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant:1014:28: required from ‘static constexpr auto std::__detail::__variant::__gen_vtable_impl<__same_return_types, std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with bool __same_return_types = true; _Result_type = void; _Visitor = main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&; _Variants = {std::variant<int, float>&, std::variant<int, float>&}; long unsigned int ...__indices = {0, 1}]’
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant:909:48: recursively required from ‘static constexpr void std::__detail::__variant::__gen_vtable_impl<__same_return_types, 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&, _Tp*) [with bool __do_cookie = false; long unsigned int __index = 0; _Tp = std::__detail::__variant::_Multi_array<void (*)(main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&, std::variant<int, float>&, std::variant<int, float>&), 2>; bool __same_return_types = true; _Result_type = void; _Visitor = main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&; long unsigned int ...__dimensions = {2, 2}; _Variants = {std::variant<int, float>&, std::variant<int, float>&}; long unsigned int ...__indices = {}]’
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant:909:48: required from ‘constexpr const _Array_type std::__detail::__variant::__gen_vtable<true, void, main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>&&, std::variant<int, float>&, std::variant<int, float>&>::_S_vtable’
/opt/ohpc/pub/compiler/gcc/9.4.0/include/c++/9.4.0/variant:1647:23: required from ‘constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with bool __use_index = false; bool __same_return_types = true; _Visitor = main(int32_t, const char**)::<lambda(auto:23&&, decltype (rref1))>; _Variants = {std::variant<int, float>&, std::variant<int, float>&}]’