
Steven Watanabe <watanabesj <at> gmail.com> writes:
AMDG
On 11/15/2011 06:10 PM, Jerry Jeremiah wrote:
Actually, I don't want a recursive variant in the normal recursive_wrapper sense. What I want is this:
typedef std::list<a> alist; typedef std::list<b> blist; typedef boost::variant<std::string ,long double ,alist::iterator ,blist::iterator ,config::iterator > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config;
But of course I can't do that because I have no idea how to forward declare config. I suspect that there is no way to do this, but I am not in the same league as everybody else when it comes to this stuff.
Any suggestions?
Wrap it in a struct and forward declare the struct.
In Christ, Steven Watanabe
, _II2 = __gnu_cxx::__normal_iterator<const boost::variant<std::basic_string<char>, long double, config_iter>*, std::vector<boost::variant<std::basic_string<char>, long double, config_iter> ]' /include/c++/4.6.1/bits/stl_vector.h:1275:58: instantiated from 'bool std::operator==(const std::vector<_Tp, _Alloc>&, const std::vector<_Tp, _Alloc>&) [with _Tp = boost::variant<std::basic_string<char>, long double, config_iter>, _Alloc = std::allocator<boost::variant<std::basic_string<char>, long double, config_iter> >]'
Thanks for the advice. I actually tried that before asking and it didn't work. But not for the obvious reason. I assumed that the addition to the variant of the extra forward declared config_iter struct was the problem but it isn't that simple. This compiles: // test program with config_iter and nothing else // compiles ok #include <boost/variant.hpp> #include <iterator> #include <string> #include <vector> #include <list> #include <map> struct config_iter; typedef boost::variant<std::string ,long double ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; struct config_iter { config_iter(const config::iterator iter) : iter_(iter) {} operator config::iterator() const { return iter_; } config::iterator operator() () const { return iter_; } protected: config::iterator iter_; }; int main() { return 0; } And so does this: // test program with config_iter and indentifier // compiles ok if identifier::operator==() is commented out #include <boost/variant.hpp> #include <iterator> #include <string> #include <vector> #include <list> #include <map> struct config_iter; typedef boost::variant<std::string ,long double ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; struct config_iter { config_iter(const config::iterator iter) : iter_(iter) {} operator config::iterator() const { return iter_; } config::iterator operator() () const { return iter_; } protected: config::iterator iter_; }; struct identifier { identifier() : name_(""), version_({0}) { // std::cout << "identifier::identifier()" << std::endl; } identifier(const std::string & name, const value & version) : name_(name), version_(version) { // std::cout << "identifier::identifier(" << name << "," << version << ")" << std::endl; } // bool operator == (const identifier & other) const // { // return name_ == other.name_ && version_ == other.version_; // } private: // updated by constructor std::string name_; value version_; }; int main() { return 0; } But if you put the operator== into the completely unrelated identifier class then even though identifier has nothing to do with the rest of the program it doesn't compile: // test program with config_iter and indentifier // doesn't compile if identifier::operator==() is in the program #include <boost/variant.hpp> #include <iterator> #include <string> #include <vector> #include <list> #include <map> struct config_iter; typedef boost::variant<std::string ,long double ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; struct config_iter { config_iter(const config::iterator iter) : iter_(iter) {} operator config::iterator() const { return iter_; } config::iterator operator() () const { return iter_; } protected: config::iterator iter_; }; struct identifier { identifier() : name_(""), version_({0}) { // std::cout << "identifier::identifier()" << std::endl; } identifier(const std::string & name, const value & version) : name_(name), version_(version) { // std::cout << "identifier::identifier(" << name << "," << version << ")" << std::endl; } bool operator == (const identifier & other) const { return name_ == other.name_ && version_ == other.version_; } private: // updated by constructor std::string name_; value version_; }; int main() { return 0; } I don't understand why the addition of an unrelated type makes a difference? The errors talk about config_iter having no comparison operator: /include/boost/variant/variant.hpp: In member function 'bool boost::detail::variant::equal_comp::operator()(const T&, const T&) const [with T = config_iter]': In file included from /include/boost/variant.hpp:17:0, from main.cpp:1: /include/boost/variant/variant.hpp:789:47: instantiated from 'bool boost::detail::variant::comparer<Variant, Comp>::operator()(const T&) const [with T = config_iter, Variant = boost::variant<std::basic_string<char>, long double, config_iter>, Comp = boost::detail::variant::equal_comp]' /include/boost/variant/variant.hpp:858:32: instantiated from 'boost::detail::variant::invoke_visitor<Visitor>::result_type boost::detail::variant::invoke_visitor<Visitor>::internal_visit(T&, int) [with T = const config_iter, Visitor = boost::detail::variant::comparer<boost::variant<std::basic_string<char>, long double, config_iter>, boost::detail::variant::equal_comp>, boost::detail::variant::invoke_visitor<Visitor>::result_type = bool]' /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::comparer<boost:: variant<std::basic_string<char>, long double, config_iter>, boost::detail::variant::equal_comp> >, VoidPtrCV = const void*, T = config_iter, typename Visitor::result_type = bool, mpl_::true_ = mpl_::bool_<true>]' /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::comparer<boost:: variant<std::basic_string<char>, long double, config_iter>, boost::detail::variant::equal_comp> >, VoidPtrCV = const void*, T = config_iter, NoBackupFlag = boost::variant<std::basic_string<char>, long double, config_iter>::has_fallback_type_, typename Visitor::result_type = bool]' /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_i tem<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, long double, boost::mpl::l_item<mpl_::long_<1l>, config_iter, boost::mpl::l_end> > > >, boost::mpl::l_iter<boost::mpl::l_end> >, Visitor = boost::detail::variant::invoke_visitor<boost::detail::variant::comparer<boost:: variant<std::basic_string<char>, long double, config_iter>, boost::detail::variant::equal_comp> >, VoidPtrCV = const void*, NoBackupFlag = boost::variant<std::basic_string<char>, long double, config_iter>::has_fallback_type_, typename Visitor::result_type = bool, mpl_::false_ = mpl_::bool_<false>]' /include/boost/variant/variant.hpp:1802:13: [ skipping 3 instantiation contexts ] /include/boost/variant/variant.hpp:1745:41: instantiated from 'bool boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::operator==(const boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>&) const [with T0_ = std::basic_string<char>, T1 = long double, T2 = config_iter, T3 = boost::detail::variant::void_, 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_, boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> = boost::variant<std::basic_string<char>, long double, config_iter>]' make[2]: Leaving directory `D:/Dynamo' /include/c++/4.6.1/bits/stl_algobase.h:791:6: instantiated from 'static bool std::__equal<_BoolType>::equal(_II1, _II1, _II2) [with _II1 = const boost::variant<std::basic_string<char>, long double, config_iter>*, _II2 = const boost::variant<std::basic_string<char>, long double, config_iter>*, bool _BoolType = false]' make[1]: Leaving directory `D:/Dynamo' /include/c++/4.6.1/bits/stl_algobase.h:820:71: instantiated from 'bool std::__equal_aux(_II1, _II1, _II2) [with _II1 = const boost::variant<std::basic_string<char>, long double, config_iter>*, _II2 = const boost::variant<std::basic_string<char>, long double, config_iter>*]' /include/c++/4.6.1/bits/stl_algobase.h:1022:37: instantiated from 'bool std::equal(_II1, _II1, _II2) [with _II1 = __gnu_cxx::__normal_iterator<const boost::variant<std::basic_string<char>, long double, config_iter>*, std::vector<boost::variant<std::basic_string<char>, long double, config_iter> main.cpp:41:58: instantiated from here /include/boost/variant/variant.hpp:807:23: error: no match for 'operator==' in 'lhs == rhs' /include/boost/variant/variant.hpp:807:23: note: candidate is: /include/boost/blank.hpp:58:13: note: bool boost::operator==(const boost::blank&, const boost::blank&) /include/boost/blank.hpp:58:13: note: no known conversion for argument 1 from 'const config_iter' to 'const boost::blank&' So I thought I would get clever and add an operator== to config_iter and that seems to compile: // test program with config_iter and indentifier // compiles ok if both have an operator== #include <boost/variant.hpp> #include <iterator> #include <string> #include <vector> #include <list> #include <map> struct config_iter; typedef boost::variant<std::string ,long double ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; struct config_iter { config_iter(const config::iterator iter) : iter_(iter) {} operator config::iterator() const { return iter_; } config::iterator operator() () const { return iter_; } bool operator == (const config_iter & other) const { return iter_ == other.iter_; } protected: config::iterator iter_; }; struct identifier { identifier() : name_(""), version_({0}) { // std::cout << "identifier::identifier()" << std::endl; } identifier(const std::string & name, const value & version) : name_(name), version_(version) { // std::cout << "identifier::identifier(" << name << "," << version << ")" << std::endl; } bool operator == (const identifier & other) const { return name_ == other.name_ && version_ == other.version_; } private: // updated by constructor std::string name_; value version_; }; int main() { return 0; } And then I added another completely unrelated class called message_iter: // test program with message_iter, config_iter and indentifier // all have an operator== // compiles ok if message_iter is below config_iter // doesn't compile if message_iter is above config_iter #include <boost/variant.hpp> #include <iterator> #include <string> #include <vector> #include <list> #include <map> struct message_iter; struct config_iter; typedef boost::variant<std::string ,long double ,message_iter ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; // compiles ok if message_iter is below config_iter struct message_iter { message_iter(const message::iterator iter) : iter_(iter) {} operator message::iterator() const { return iter_; } message::iterator operator() () const { return iter_; } bool operator == (const message_iter & other) const { return iter_ == other.iter_; } protected: message::iterator iter_; }; struct config_iter { config_iter(const config::iterator iter) : iter_(iter) {} operator config::iterator() const { return iter_; } config::iterator operator() () const { return iter_; } bool operator == (const config_iter & other) const { return iter_ == other.iter_; } protected: config::iterator iter_; }; struct identifier { identifier() : name_(""), version_({0}) { // std::cout << "identifier::identifier()" << std::endl; } identifier(const std::string & name, const value & version) : name_(name), version_(version) { // std::cout << "identifier::identifier(" << name << "," << version << ")" << std::endl; } bool operator == (const identifier & other) const { return name_ == other.name_ && version_ == other.version_; } private: // updated by constructor std::string name_; value version_; }; int main() { return 0; } If you add it below config_iter everything compiles. If you add it above config_iter then it doesn't compile. Why does the positiion of a completely unrealted calss change anything? It complains about config_iter not being a complete type. /include/boost/mpl/sizeof.hpp: In instantiation of 'boost::mpl::sizeof_<config_iter>': In file included from /include/boost/variant/variant.hpp:81:0, from /include/boost/variant.hpp:17, from main.cpp:1: /include/boost/mpl/aux_/has_type.hpp:20:1: instantiated from 'boost::mpl::aux::has_type<boost::mpl::sizeof_<config_iter>, mpl_::bool_<true> >' /include/boost/mpl/aux_/preprocessed/gcc/quote.hpp:32:36: instantiated from 'boost::mpl::quote1<boost::mpl::sizeof_, mpl_::void_>::apply<config_iter>' /include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:36:8: instantiated from 'boost::mpl::apply_wrap1<boost::mpl::quote1<boost::mpl::sizeof_, mpl_::void_>, config_iter>' /include/boost/mpl/aux_/preprocessed/gcc/bind.hpp:144:21: instantiated from 'boost::mpl::bind1<boost::mpl::quote1<boost::mpl::sizeof_, mpl_::void_>, mpl_::arg<1> >::apply<config_iter>' /include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:36:8: [ skipping 8 instantiation contexts ] /include/boost/mpl/reverse_fold.hpp:41:18: instantiated from 'boost::mpl::reverse_fold<boost::mpl::l_item<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, long double, boost::mpl::l_item<mpl_::long_<1l>, config_iter, boost::mpl::l_end> > >, boost::mpl::l_end, boost::mpl::bind2<boost::mpl::push_front<mpl_::na, mpl_::na>, mpl_::arg<1>, boost::mpl::bind1<boost::mpl::protect<boost::mpl::bind1<boost::mpl::quote1<boos t::mpl::sizeof_, mpl_::void_>, mpl_::arg<1> >, 0>, mpl_::arg<2> > >, mpl_::arg<1> >' /include/boost/mpl/transform.hpp:56:8: instantiated from 'boost::mpl::aux::reverse_transform1_impl<boost::mpl::l_item<mpl_::long_<3 l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, long double, boost::mpl::l_item<mpl_::long_<1l>, config_iter, boost::mpl::l_end> > >, boost::mpl::sizeof_<mpl_::arg<1> >, boost::mpl::front_inserter<boost::mpl::l_end> >' /include/boost/mpl/transform.hpp:113:1: instantiated from 'boost::mpl::transform1<boost::mpl::l_item<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, long double, boost::mpl::l_item<mpl_::long_<1l>, config_iter, boost::mpl::l_end> > >, boost::mpl::sizeof_<mpl_::arg<1> >, mpl_::na>' /include/boost/variant/variant.hpp:123:57: instantiated from 'boost::detail::variant::max_value<boost::mpl::l_item<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, long double, boost::mpl::l_item<mpl_::long_<1l>, config_iter, boost::mpl::l_end> > >, boost::mpl::sizeof_<mpl_::arg<1> > >' /include/boost/variant/variant.hpp:248:17: instantiated from 'boost::detail::variant::make_storage<boost::mpl::l_item<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, long double, boost::mpl::l_item<mpl_::long_<1l>, config_iter, boost::mpl::l_end> > >, boost::variant<std::basic_string<char>, long double, config_iter>::has_fallback_type_>' /include/boost/variant/variant.hpp:1131:17: instantiated from 'boost::variant<std::basic_string<char>, long double, config_iter>' main.cpp:25:31: instantiated from here /include/boost/mpl/sizeof.hpp:26:8: error: invalid application of 'sizeof' to incomplete type 'config_iter' The goal, of course, is to include both in the variant: struct message_iter; struct config_iter; typedef boost::variant<std::string ,long double ,message_iter ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; But it won't compile because each of message_iter and config_iter need to be above the other so it doesn't compile. If I remove the ALL operator== it compiles but of course identifier needs its operator==. So what can I do? Is there any way to get this (below) to compile with the identifier::operator== () in the program? // test program with message_iter, config_iter and indentifier // compiles ok if NONE have an operator== // doesn't compile if ANY have an operator== #include <boost/variant.hpp> #include <iterator> #include <string> #include <vector> #include <list> #include <map> struct message_iter; struct config_iter; typedef boost::variant<std::string ,long double ,message_iter ,config_iter > var; typedef std::vector<var> value; typedef std::map<std::string,value> message; typedef std::map<std::string,message> config; struct config_iter { config_iter(const config::iterator iter) : iter_(iter) {} operator config::iterator() const { return iter_; } config::iterator operator() () const { return iter_; } // bool operator == (const config_iter & other) const // { // return iter_ == other.iter_; // } protected: config::iterator iter_; }; struct message_iter { message_iter(const message::iterator iter) : iter_(iter) {} operator message::iterator() const { return iter_; } message::iterator operator() () const { return iter_; } // bool operator == (const message_iter & other) const // { // return iter_ == other.iter_; // } protected: message::iterator iter_; }; struct identifier { identifier() : name_(""), version_({0}) { // std::cout << "identifier::identifier()" << std::endl; } identifier(const std::string & name, const value & version) : name_(name), version_(version) { // std::cout << "identifier::identifier(" << name << "," << version << ")" << std::endl; } // bool operator == (const identifier & other) const // { // return name_ == other.name_ && version_ == other.version_; // } private: // updated by constructor std::string name_; value version_; }; int main() { return 0; } I'm sorry I was off on the wrong track with my original question. Do you have any suggestions for getthing that last program to compile with identifier::operator==() in the program? Tahnks for the advice, Jerry