Opened 10 years ago

Closed 6 years ago

#7120 closed Bugs (fixed)

ambiguous overload of convert_construct in variant when one of variant's value types derives from variant

Reported by: jeffrey.hellrung Owned by: Antony Polukhin
Milestone: Boost 1.64.0 Component: variant
Version: Boost 1.51.0 Severity: Problem
Keywords: Cc:

Description

#include <boost/variant.hpp>

struct X

: boost::variant< int >

{ };

void main() {

X x; boost::variant<X> y(x);

}

yields (MSVC9)

1>------ Build started: Project: scratch, Configuration: Debug Win32 ------ 1>Compiling... 1>main.cpp 1>c:\users\jeffrey\boost_1_49_0\boost\variant\variant.hpp(1405) : error C2666: 'boost::variant<T0_>::convert_construct' : 3 overloads have similar conversions 1> with 1> [ 1> T0_=X 1> ] 1> c:\users\jeffrey\boost_1_49_0\boost\variant\variant.hpp(1384): 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<int> &,long)' 1> with 1> [ 1> T0_=X 1> ] 1> c:\users\jeffrey\boost_1_49_0\boost\variant\variant.hpp(1375): or '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_>(boost::variant<int> &,long)' 1> with 1> [ 1> T0_=X 1> ] 1> c:\users\jeffrey\boost_1_49_0\boost\variant\variant.hpp(1315): or 'void boost::variant<T0_>::convert_construct<T>(T &,int,boost::mpl::false_)' 1> with 1> [ 1> T0_=X, 1> T=X 1> ] 1> while trying to match the argument list '(X, long)' 1> c:\users\jeffrey\scratch\main.cpp(10) : see reference to function template instantiation 'boost::variant<T0_>::variant<X>(T &)' being compiled 1> with 1> [ 1> T0_=X, 1> T=X 1> ]

Basically, the problem appears to be the call to

convert_construct(operand, 1L) operand is of type X

which cannot disambiguate between the overloads (simplified)

void convert_construct([const] boost::variant<T>& operand, long); void convert_construct(T& operand, int);

The former requires a derived->base conversion in the first argument, while the latter requires a long->int conversion in the second argument. Perhaps the dispatching among the convert_construct overloads should be more sophisticated?

Change History (6)

comment:1 by Antony Polukhin, 6 years ago

Milestone: To Be DeterminedBoost 1.62.0
Owner: changed from ebf to Antony Polukhin
Status: newassigned

comment:2 by Antony Polukhin, 6 years ago

Fixed in d23cdd35 develop, will be merged to master branch as soon as the tests will cycle.

comment:3 by anonymous, 6 years ago

Any workaround for this? I have the exact same problem.

in reply to:  2 comment:4 by Igor R., 6 years ago

Replying to apolukhin:

Fixed in d23cdd35 develop, will be merged to master branch as soon as the tests will cycle.

Just for the record: the proposed fix fails the following code:

#include <boost/variant.hpp>
#include <array>

template<class Node>
struct node1_type;

struct var_type;

using var_base = boost::variant<int, 
  boost::recursive_wrapper<node1_type<var_type>>
>;

template<class Node>
struct node1_type
{
  std::array<Node, 1> children;
};

struct var_type : var_base
{
  using var_base::var_base;
};

int main()
{
  var_type v1 = 1;
}

comment:5 by Antony Polukhin, 6 years ago

Milestone: Boost 1.62.0Boost 1.64.0

Fixed by Mikhail Maximov in 217ee7f9. Test case was added in fbad41fb. As soon as the tests will cycle, will be merged to master branch.

comment:6 by Antony Polukhin, 6 years ago

Resolution: fixed
Status: assignedclosed
Note: See TracTickets for help on using tickets.