EDIT:
The question was marked as a dup of std::function template argument resolution, but it doesn't seem the same to me because In my case, VisitImpl is not a function template, and neither are the callbacks that it takes as second param. At the callsite of VisitImpl, the compiler knows the type of the callback. Plus, the deduction works for when I comment out the VisitImpl for VisitBoolCb and leave in the other 2 overloads.
ORIGINAL:
I don't understand why Visual Studio 2017 fails to choose the correct overload in this case. If I comment out the overload
void VisitImpl(Arg& arg, VisitBoolCb cb)
... then the compiles.
using Arg = std::variant<bool, int_t, double, std::string_view>;
using VisitBoolCb = std::function<void(bool)>;
using VisitIntCb = std::function<void(int_t)>;
using VisitSymbolCb = std::function<void(std::string_view)>;
void VisitImpl(Arg& arg, VisitBoolCb cb) {}
void VisitImpl(Arg& arg, VisitIntCb cb) {}
void VisitImpl(Arg& arg, VisitSymbolCb cb) {}
void Visit(Arg& val) {}
template<typename Visitor, typename... Rest>
void Visit(Arg& arg, Visitor vis, Rest... rest) {
VisitImpl(arg, vis); // HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Visit(arg, rest...);
}
// The template visit is called from here.
Visit(a, [](int_t val) {
std::cout << "int is: " << val << "\n";
});
I get these errors:
error C2668: 'VisitImpl': ambiguous call to overloaded function
note: could be 'void VisitImpl(Arg &,VisitSymbolCb)'
note: or 'void VisitImpl(Arg &,VisitIntCb)'
note: or 'void VisitImpl(Arg &,VisitBoolCb)'
note: while trying to match the argument list '(Arg, SomeStruct::()::<lambda_49c2998d9df82f26cda7a01b5ed892aa>)'