boost::variant and function overload resolution

boost, c++

Solution

The problem is the constructor

template<typename T>
variant(const T&)

of `boost::variant`. The code below reproduces the problem without all the magic:

struct C {};

struct A {
  A(const C&) {}

  template<typename T>
  A(const T&) {}
};
struct B {
  template<typename T>
  B(const T&) {}
};

int f(const A&) {
    return 0;
}
int f(const B&) {
    return 1;
}
int main() {
  return f(C{});
}

I think the `variant` constructor should only be enabled if the argument is actually convertible to the arguments, you might want to raise this as a bug.

Problem

The following code doesn't compile: ``` #include <boost/variant.hpp> class A {}; class B {}; class C {}; class D {}; using v1 = boost::variant<A, B>; using v2 = boost::variant<C, D>; int f(v1 const&) { return 0; } int f(v2 const&) { return 1; } int main() { return f(A{}); } ``` both gcc and clang complains with: ``` test1.cpp: In function ‘int main()’: test1.cpp:18:17: error: call of overloaded ‘f(A)’ is ambiguous return f(A{}); ^ test1.cpp:18:17: note: candidates are: test1.cpp:11:5: note: int f(const v1&) int f(v1 const&) { ^ test1.cpp:14:5: note: int f(const v2&) int f(v2 const&) { ``` Given that is not possible to construct a `v2` object from an `A` instance why the compiler gives the same priority to both functions during the overload resolution?

Original source