If I write this code it still compiles:
namespace MyNamespace
{
struct STreeConstructionRuleQuery : std::string {};
struct STreeConstructionRuleOperation : std::string {};
struct STreeConstructionRuleOperand : std::string {};
struct STreeConstructionRuleCondition : std::string {};
struct STreeConstructionRuleOperationWithOperands : boost::tuple<STreeConstructionRuleOperation, std::vector<STreeConstructionRuleOperand> > {};
struct STreeConstructionRule
{
boost::optional<std::vector<std::vector<STreeConstructionRuleOperationWithOperands> > > m_sAssertion;
STreeConstructionRuleQuery m_sQuery;
STreeConstructionRuleOperationWithOperands m_sAction;
boost::optional<STreeConstructionRuleCondition> m_sCondition;
};
}
BOOST_FUSION_ADAPT_STRUCT(
MyNamespace::STreeConstructionRule,
(boost::optional<std::vector<std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> > >, m_sAssertion)
(MyNamespace::STreeConstructionRuleQuery, m_sQuery)
(MyNamespace::STreeConstructionRuleOperationWithOperands, m_sAction)
(boost::optional<MyNamespace::STreeConstructionRuleCondition>, m_sCondition)
)
namespace MyNamespace
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
template <typename Iterator>
struct STreeContructionRulesGrammar : qi::grammar<Iterator, std::vector<STreeConstructionRule>(), ascii::space_type>
{
qi::rule<Iterator, std::vector<STreeConstructionRule>(), ascii::space_type> m_oStart;
qi::rule<Iterator, qi::unused_type(), ascii::space_type> m_oComment;
qi::rule<Iterator, STreeConstructionRule(), ascii::space_type> m_oRule;
STreeContructionRulesGrammar() : STreeContructionRulesGrammar::base_type(m_oStart)
{
m_oStart = *(m_oComment | m_oRule [phoenix::push_back(qi::_val, qi::_1)]);
m_oComment = (("-->" >> *(qi::char_) >> "<--") | ('#' >> *(qi::char_ - qi::char_("\n\r"))));
}
};
}
But when I change the definition of STreeConstructionRuleOperand to
struct STreeConstructionRuleOperand : boost::variant<int> {};
I get the following compilation error (STLPort is used instead of STL):
1>d:\commonlib\include\boost\variant\variant.hpp(1373) : error C2666: 'boost::variant<T0_>::convert_construct' : 2 overloads have similar conversions
1> with
1> [
1> T0_=int
1> ]
1> d:\commonlib\include\boost\variant\variant.hpp(1358): could be 'void boost::variant<T0_>::convert_construct<int,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_,boost::detail::variant::void_>(const boost::variant<T0_> &,long)'
1> with
1> [
1> T0_=int
1> ]
1> d:\commonlib\include\boost\variant\variant.hpp(1289): or 'void boost::variant<T0_>::convert_construct<const T>(T &,int,boost::mpl::false_)'
1> with
1> [
1> T0_=int,
1> T=MyNamespace::STreeConstructionRuleOperand
1> ]
1> while trying to match the argument list '(const MyNamespace::STreeConstructionRuleOperand, long)'
1> d:\commonlib\include\boost\fusion\container\vector\detail\vector_n.hpp(45) : see reference to function template instantiation 'boost::variant<T0_>::variant<MyNamespace::STreeConstructionRuleOperand>(const T &)' being compiled
1> with
1> [
1> T0_=int,
1> T=MyNamespace::STreeConstructionRuleOperand
1> ]
1> d:\commonlib\include\stlport\stl\_uninitialized.h(93) : see reference to function template instantiation 'void stlpd_std::_Destroy_Range<_OutputIter>(_ForwardIterator,_ForwardIterator)' being compiled
1> with
1> [
1> _OutputIter=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *,
1> _ForwardIterator=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *
1> ]
1> d:\commonlib\include\stlport\stl\_uninitialized.h(113) : see reference to function template instantiation '_OutputIter stlpd_std::priv::__ucopy<_InputIter,_OutputIter,ptrdiff_t>(_RandomAccessIter,_RandomAccessIter,_OutputIter,const stlpd_std::random_access_iterator_tag &,_Distance *)' being compiled
1> with
1> [
1> _OutputIter=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *,
1> _InputIter=const stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *,
1> _RandomAccessIter=const stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *,
1> _Distance=ptrdiff_t
1> ]
1> d:\commonlib\include\stlport\stl\_vector.h(249) : see reference to function template instantiation '_OutputIter stlpd_std::priv::__ucopy_ptrs<const stlpd_std::vector<_Tp>*,stlpd_std::vector<_Tp>*>(_InputIter,_InputIter,_OutputIter,const stlpd_std::__false_type &)' being compiled
1> with
1> [
1> _OutputIter=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *,
1> _Tp=MyNamespace::STreeConstructionRuleOperationWithOperands,
1> _InputIter=const stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands> *
1> ]
1> d:\commonlib\include\stlport\stl\_vector.h(246) : while compiling class template member function 'stlpd_std::priv::_NonDbg_vector<_Tp,_Alloc>::_NonDbg_vector(const stlpd_std::priv::_NonDbg_vector<_Tp,_Alloc> &)'
1> with
1> [
1> _Tp=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>,
1> _Alloc=stlpd_std::allocator<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>
1> ]
1> d:\commonlib\include\stlport\stl\debug\_iterator.h(378) : see reference to class template instantiation 'stlpd_std::priv::_NonDbg_vector<_Tp,_Alloc>' being compiled
1> with
1> [
1> _Tp=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>,
1> _Alloc=stlpd_std::allocator<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>
1> ]
1> d:\commonlib\include\stlport\stl\debug\_vector.h(106) : see reference to class template instantiation 'stlpd_std::priv::__construct_checker<_Container>' being compiled
1> with
1> [
1> _Container=stlpd_std::priv::_NonDbg_vector<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>,stlpd_std::allocator<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>>
1> ]
1> d:\commonlib\include\boost\optional\optional.hpp(110) : see reference to class template instantiation 'stlpd_std::vector<_Tp>' being compiled
1> with
1> [
1> _Tp=stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>
1> ]
1> d:\commonlib\include\boost\optional\optional.hpp(113) : see reference to class template instantiation 'boost::optional_detail::aligned_storage<T>::dummy_u' being compiled
1> with
1> [
1> T=stlpd_std::vector<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>
1> ]
1> d:\commonlib\include\boost\optional\optional.hpp(450) : see reference to class template instantiation 'boost::optional_detail::aligned_storage<T>' being compiled
1> with
1> [
1> T=stlpd_std::vector<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>
1> ]
1> d:\commonlib\include\boost\optional\optional.hpp(457) : see reference to class template instantiation 'boost::optional_detail::optional_base<T>' being compiled
1> with
1> [
1> T=stlpd_std::vector<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>
1> ]
1> d:\preformator\sources\prefcore\preftreeconstructor.cpp(52) : see reference to class template instantiation 'boost::optional<T>' being compiled
1> with
1> [
1> T=stlpd_std::vector<stlpd_std::vector<MyNamespace::STreeConstructionRuleOperationWithOperands>>
1> ]
This is the only error the compiler reports. I don’t see any ambiguity but the compiler does. What is the reason for this error and how it should be fixed?
Two things strike me here:
how would something that is used to be
std::string, be assigned to something that is a now avariant<int>?The code shown doesn’t include the code that would explain this (as it is probably in
m_oRuleor a subrule of that). But perhaps avariant<std::string>poses fewer problems, seeing how you had astd::stringvalue to assign before.You appear to abuse
structinheritance quite a lot to achievetypedefbehaviour. Note that public inheritance is not the same as atypedef, especially with regards to the constructors (which are not inherited).Try replacing each use of
by the more usual idiom of
I actually expect the latter to solve the issue, since you are running into constructor overload trouble.
Regardless of that, I have only tested with gcc, boost_1_51_0 and GNU libstdc++. It compiles everything you posted without a hitch (but again, not you left out crucial elements, such as the rule
m_oRulethat does the actual assigning toRuleOpWithOperands).Demonstration FauxTypedef:
Demonstrating the relevant problem (at least one) with inheritance instead of
typedef:If you insist on having a _unique
typeidfor the typedef-ed name, you can resort to BOOST_STRONG_TYPEDEF