2013-11-03 2 views
0

Я пытаюсь научиться использовать Boost :: variant, используя базовое онлайн-обучение Boost по адресу (http://www.boost.org/doc/libs/1_34_0/doc/html/variant/tutorial.html). Для того, чтобы получить повесить его, я пытался принимать часть кода из учебника (ниже) ...C++ Boost :: вариант с использованием boost :: get on my user defined type

#include "boost/variant.hpp" 
#include <iostream> 
#include <complex> 

void times_two(boost::variant<int, std::string, std::complex<double> > & v) { 
    if (int* pi = boost::get<int>(&v)) 
     *pi *= 2; 
    else if (std::string* pstr = boost::get<std::string>(&v)) 
     *pstr += *pstr; 
    //No check for complex - will silently return when variant is complex (BAD). 
} 

int main() { 
    boost::variant<int, std::string, std::complex<double> > v; 
    v = "hello"; 
    std::string& str = boost::get<std::string>(v); 
    str += " world! "; 
//the std::string contained by v now is equal to "hello world! ". Again, we can demonstrate this by streaming v to standard output: 
    std::cout << v << std::endl; 
    times_two(v); 
    std::cout << v << std::endl; 
    std::complex<double> a(5.0, 6.0); 
    v = a; 
    times_two(v); 
    return 0; 
} 

^Это нормально компилируется и возвращается «Привет мир! привет мир! Привет мир!» как и ожидалось, взяв сложный тип перед возвратом.

Затем я попытался изменить его ...

Но как только я добавил свою собственную-структуру, «structy» в варианте пример программу, например, так:

#include "boost/variant.hpp" 
#include <iostream> 
#include <complex> 

struct structy { 
    int a; 
}; 

void times_two(
     boost::variant<int, std::string, std::complex<double>, structy> & v) { 
    if (int* pi = boost::get<int>(&v)) 
     *pi *= 2; 
    else if (std::string* pstr = boost::get<std::string>(&v)) 
     *pstr += *pstr; 
    //No check for complex or structy - should silently returns. 
} 

int main() { 

    boost::variant<int, std::string, std::complex<double>, structy> v; 
    v = "hello"; 
    std::string& str = boost::get<std::string>(v); 
    str += " world! "; 
//As desired, the std::string contained by v now is equal to "hello world! ". Again, we can demonstrate this by streaming v to standard output: 
    std::cout << v << std::endl; 
    times_two(v); 
    std::cout << v << std::endl; 
    std::complex<double> a(5.0, 6.0); 
    v = a; 
    times_two(v); 
    return 0; 
} 

я получил массивную ошибку сообщение при компиляции с g ++ 4.7. Я не понимаю, что он говорит, но я включу его для справки.

Почему я не могу заставить его работать с типами данных, которые я определяю? Обратите внимание, что я получаю такое же очень громкое сообщение об ошибке, когда пытаюсь использовать boost :: static_visitor с моими собственными пользовательскими классами.

Большое сообщение об ошибке ниже:

[email protected]:~/Downloads/boost_1_54_0$ g++ ~/temp.cpp -o temp 
In file included from /usr/local/include/boost/variant/variant.hpp:2416:0, 
      from /usr/local/include/boost/variant.hpp:17, 
      from /home/johnmichaelreed/temp.cpp:1: 
/usr/local/include/boost/variant/detail/variant_io.hpp: In member function ‘void boost::detail::variant::printer<OStream>::operator()(const T&) const [with T = structy, OStream = std::basic_ostream<char>]’: 
/usr/local/include/boost/variant/variant.hpp:1017:32: instantiated from ‘boost::detail::variant::invoke_visitor<Visitor>::result_type boost::detail::variant::invoke_visitor<Visitor>::internal_visit(T&, int) [with T = const structy, Visitor = boost::detail::variant::printer<std::basic_ostream<char> >, boost::detail::variant::invoke_visitor<Visitor>::result_type = void]’ 
/usr/local/include/boost/variant/detail/visitation_impl.hpp:130:9: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl_invoke_impl(int, Visitor&, VoidPtrCV, T*, mpl_::true_) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char> > >, VoidPtrCV = const void*, T = structy, typename Visitor::result_type = void, mpl_::true_ = mpl_::bool_<true>]’ 
/usr/local/include/boost/variant/detail/visitation_impl.hpp:173:9: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl_invoke(int, Visitor&, VoidPtrCV, T*, NoBackupFlag, int) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char> > >, VoidPtrCV = const void*, T = structy, NoBackupFlag = boost::variant<int, std::basic_string<char>, std::complex<double>, structy>::has_fallback_type_, typename Visitor::result_type = void]’ 
/usr/local/include/boost/variant/detail/visitation_impl.hpp:260:1: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = mpl_::int_<0>, step0 = boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<4l>, int, boost::mpl::l_item<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, std::complex<double>, boost::mpl::l_item<mpl_::long_<1l>, structy, boost::mpl::l_end> > > > >, boost::mpl::l_iter<boost::mpl::l_end> >, Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char> > >, VoidPtrCV = const void*, NoBackupFlag = boost::variant<int, std::basic_string<char>, std::complex<double>, structy>::has_fallback_type_, typename Visitor::result_type = void, mpl_::false_ = mpl_::bool_<false>]’ 
/usr/local/include/boost/variant/variant.hpp:2326:13: instantiated from ‘static typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char> > >, VoidPtrCV = const void*, T0_ = int, T1 = std::basic_string<char>, T2 = std::complex<double>, T3 = structy, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_, typename Visitor::result_type = void]’ 
/usr/local/include/boost/variant/variant.hpp:2348:13: instantiated from ‘typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor(Visitor&) const [with Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::printer<std::basic_ostream<char> > >, T0_ = int, T1 = std::basic_string<char>, T2 = std::complex<double>, T3 = structy, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_, typename Visitor::result_type = void]’ 
/usr/local/include/boost/variant/variant.hpp:2370:52: instantiated from ‘typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::apply_visitor(Visitor&) const [with Visitor = boost::detail::variant::printer<std::basic_ostream<char> >, T0_ = int, T1 = std::basic_string<char>, T2 = std::complex<double>, T3 = structy, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_, typename Visitor::result_type = void]’ 
/usr/local/include/boost/variant/detail/variant_io.hpp:88:5: instantiated from ‘std::basic_ostream<E, T>& boost::operator<<(std::basic_ostream<E, T>&, const boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&) [with E = char, T = std::char_traits<char>, U0 = int, U1 = std::basic_string<char>, U2 = std::complex<double>, U3 = structy, U4 = boost::detail::variant::void_, U5 = boost::detail::variant::void_, U6 = boost::detail::variant::void_, U7 = boost::detail::variant::void_, U8 = boost::detail::variant::void_, U9 = boost::detail::variant::void_, U10 = boost::detail::variant::void_, U11 = boost::detail::variant::void_, U12 = boost::detail::variant::void_, U13 = boost::detail::variant::void_, U14 = boost::detail::variant::void_, U15 = boost::detail::variant::void_, U16 = boost::detail::variant::void_, U17 = boost::detail::variant::void_, U18 = boost::detail::variant::void_, U19 = boost::detail::variant::void_]’ 
/home/johnmichaelreed/temp.cpp:25:16: instantiated from here 
/usr/local/include/boost/variant/detail/variant_io.hpp:64:9: error: no match for ‘operator<<’ in ‘((const boost::detail::variant::printer<std::basic_ostream<char> >*)this)->boost::detail::variant::printer<std::basic_ostream<char> >::out_ << operand’ 
/usr/local/include/boost/variant/detail/variant_io.hpp:64:9: note: candidates are: 
/usr/include/c++/4.6/ostream:110:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:110:7: note: no known conversion for argument 1 from ‘const structy’ to ‘std::basic_ostream<char>::__ostream_type& (*)(std::basic_ostream<char>::__ostream_type&) {aka std::basic_ostream<char>& (*)(std::basic_ostream<char>&)}’ 
/usr/include/c++/4.6/ostream:119:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>, std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>] 
/usr/include/c++/4.6/ostream:119:7: note: no known conversion for argument 1 from ‘const structy’ to ‘std::basic_ostream<char>::__ios_type& (*)(std::basic_ostream<char>::__ios_type&) {aka std::basic_ios<char>& (*)(std::basic_ios<char>&)}’ 
/usr/include/c++/4.6/ostream:129:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:129:7: note: no known conversion for argument 1 from ‘const structy’ to ‘std::ios_base& (*)(std::ios_base&)’ 
/usr/include/c++/4.6/ostream:167:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:167:7: note: no known conversion for argument 1 from ‘const structy’ to ‘long int’ 
/usr/include/c++/4.6/ostream:171:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:171:7: note: no known conversion for argument 1 from ‘const structy’ to ‘long unsigned int’ 
/usr/include/c++/4.6/ostream:175:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:175:7: note: no known conversion for argument 1 from ‘const structy’ to ‘bool’ 
/usr/include/c++/4.6/bits/ostream.tcc:93:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] 
/usr/include/c++/4.6/bits/ostream.tcc:93:5: note: no known conversion for argument 1 from ‘const structy’ to ‘short int’ 
/usr/include/c++/4.6/ostream:182:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:182:7: note: no known conversion for argument 1 from ‘const structy’ to ‘short unsigned int’ 
/usr/include/c++/4.6/bits/ostream.tcc:107:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] 
/usr/include/c++/4.6/bits/ostream.tcc:107:5: note: no known conversion for argument 1 from ‘const structy’ to ‘int’ 
/usr/include/c++/4.6/ostream:193:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:193:7: note: no known conversion for argument 1 from ‘const structy’ to ‘unsigned int’ 
/usr/include/c++/4.6/ostream:202:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:202:7: note: no known conversion for argument 1 from ‘const structy’ to ‘long long int’ 
/usr/include/c++/4.6/ostream:206:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:206:7: note: no known conversion for argument 1 from ‘const structy’ to ‘long long unsigned int’ 
/usr/include/c++/4.6/ostream:211:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:211:7: note: no known conversion for argument 1 from ‘const structy’ to ‘double’ 
/usr/include/c++/4.6/ostream:215:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:215:7: note: no known conversion for argument 1 from ‘const structy’ to ‘float’ 
/usr/include/c++/4.6/ostream:223:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:223:7: note: no known conversion for argument 1 from ‘const structy’ to ‘long double’ 
/usr/include/c++/4.6/ostream:227:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/include/c++/4.6/ostream:227:7: note: no known conversion for argument 1 from ‘const structy’ to ‘const void*’ 
/usr/include/c++/4.6/bits/ostream.tcc:121:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>] 
/usr/include/c++/4.6/bits/ostream.tcc:121:5: note: no known conversion for argument 1 from ‘const structy’ to ‘std::basic_ostream<char>::__streambuf_type* {aka std::basic_streambuf<char>*}’ 
/usr/local/include/boost/blank.hpp:93:46: note: template<class E, class T> std::basic_ostream<_CharT, _Traits>& boost::operator<<(std::basic_ostream<_CharT, _Traits>&, const boost::blank&) 
/usr/local/include/boost/variant/detail/variant_io.hpp:79:46: note: template<class E, class T, class U0, class U1, class U2, class U3, class U4, class U5, class U6, class U7, class U8, class U9, class U10, class U11, class U12, class U13, class U14, class U15, class U16, class U17, class U18, class U19> std::basic_ostream<E, T>& boost::operator<<(std::basic_ostream<E, T>&, const boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&) 
/usr/include/c++/4.6/complex:521:5: note: template<class _Tp, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::complex<_Tp>&) 
/usr/include/c++/4.6/ostream:528:5: note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const unsigned char*) 
/usr/include/c++/4.6/ostream:523:5: note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const signed char*) 
/usr/include/c++/4.6/ostream:510:5: note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*) 
/usr/include/c++/4.6/bits/ostream.tcc:323:5: note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*) 
/usr/include/c++/4.6/ostream:493:5: note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const _CharT*) 
/usr/include/c++/4.6/ostream:473:5: note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char) 
/usr/include/c++/4.6/ostream:468:5: note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char) 
/usr/include/c++/4.6/ostream:462:5: note: template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, char) 
/usr/include/c++/4.6/ostream:456:5: note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char) 
/usr/include/c++/4.6/ostream:451:5: note: template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, _CharT) 
/usr/include/c++/4.6/bits/basic_string.h:2693:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&) 
[email protected]:~/Downloads/boost_1_54_0$ 

Что означает эта ошибка? Почему моя модификация нарушила код?

+0

Это может быть ваш тип, не перегружающий 'operator <<'. – chris

+0

Я никогда не присваиваю свой вариант «structy» определенного типа, и я, конечно же, не пытался использовать на нем оператор потока или пытаюсь его распечатать, поэтому я не думал, что перегрузка оператора потока для structy было необходимо для его компиляции. –

+0

Я подозреваю, что это потому, что вы выводите вариант. http://coliru.stacked-crooked.com/a/fc68b2b14287ecd3 – chris

ответ

1

@chris верен в своем предположении, это из-за недостающего оператора < <.

Эти ошибки являются «по дизайну» Boost.Variant, они мешают вам забыть сделать что-то, что вам нужно сделать, чтобы определить правильный variant.

Действительно, когда вы используете boost::variant<T1,T2,T3> v с некоторыми функциями или оператором, вы ожидаете, что у вас будет какая-то обработка для случая, когда переменная v имеет тип T1, а другая обработка для случая имеет тип T2 и даже некоторые обработка для случая, когда v фактически относится к типу T3.

Когда вы читаете учебник по варианту далее, вы обнаружите, что рекомендуемая реализация функции times_two проходит через посетителя варианта. В отличие от вашей (начальной) реализации, последний также выдавал бы ошибку, если программист забыл реализовать функцию посещения (aka operator()) для некоторых типов T1, T2, T3.

Теперь такая реализация посетителя уже установлена ​​на место (по Boost) для стандартных функций C++, таких как operator <<(variant<...>,ostream&). Так как ваш struct structy не позволяет оператору < <, компилятор выдает сообщение об ошибке.

Несчастливый эффект заключается в том, что ошибка несколько загадочна. Часто бывает, что ошибки вызваны оператором < <, потому что у C++ столько перегрузок для него, и компилятор пытается и упоминает их все.

Смежные вопросы