Here's a cut down example of what I'm trying to do:
#include <string>
#include <iostream>
#include <type_traits>
template <typename T>
class foo
{
public:
template <typename U>
typename std::enable_if<std::is_same<T, U>::value>::type
bar(const U& t)
{
std::cout << t << "\n";
}
};
template <typename... Args>
class baz
: public foo<Args>...
{
};
int main()
{
baz<double, std::string> b;
b.bar(1.0);
}
This gives me ambiguous function errors:
error: request for member 'bar' is ambiguous b.bar(1.0); note: candidates are: template<class U> typename std::enable_if<std::is_same<T, U>::value>::type foo<T>::bar(const U&) [with U = U; T = std::basic_string<char>] note: template<class U> typename std::enable_if<std::is_same<T, U>::value>::type foo<T>::bar(const U&) [with U = U; T = double]
My questions are twofold:
U
not deduced? I'm supposing that it's due to ordering of template deduction and overload resolution, but can someone explain this?I think the error message is misleading. The problem is actually name bar
is available in multiple base classes and you've not used using
directive to bring the names you want into the derived class scope.
Here is one working solution:
template <typename X, typename... Args>
class baz : public foo<X>, public baz<Args...>
{
public:
using foo<X>::bar; //bring the name from the first base
using baz<Args...>::bar; //bring the name from the second base
};
template <typename X>
class baz<X> : public foo<X> //specialization for one argument
{
//no using directive needed, as there is one base only!
};