C ++ 11: Desambiguar membro da classe em herança múltipla
Suponha que eu tenho esse modelo de classe base variável:
template <typename ... Types>
class Base
{
public:
// The member foo() can only be called when its template
// parameter is contained within the Types ... pack.
template <typename T>
typename std::enable_if<Contains<T, Types ...>::value>::type
foo() {
std::cout << "Base::foo()\n";
}
};
ofoo()
membro só pode ser chamado quando seu parâmetro de modelo corresponde a pelo menos um dos parâmetros deBase
(A implementação deContains
está listado na parte inferior deste post):
Base<int, char>().foo<int>(); // fine
Base<int, char>().foo<void>(); // error
Agora eu defino uma classe derivada que herda duas vezes de Base, usandoconjuntos sem sobreposição dos tipos:
struct Derived: public Base<int, char>,
public Base<double, void>
{};
Eu esperava que ao ligar, por exemplo,
Derived().foo<int>();
o compilador descobriria qual classe base usar, porque é SFINAE fora daquela que não contémint
. No entanto, o GCC 4.9 e o Clang 3.5 reclamam de uma chamada ambígua.
Minha pergunta então é dupla:
Por que o compilador não pode resolver essa ambiguidade (interesse geral)?O que posso fazer para fazer isso funcionar, sem precisar escreverDerived().Base<int, char>::foo<int>();
? EDITAR: GuyGreer me mostrou que a chamada não é ambígua quando adiciono duas declarações de uso. No entanto, como estou fornecendo a classe base para a herança do usuário, essa não é a solução ideal. Se possível, não quero que meus usuários adicionem essas declarações (que podem ser bastante detalhadas e repetitivas para grandes listas de tipos) às classes derivadas.Implementação deContains
:
template <typename T, typename ... Pack>
struct Contains;
template <typename T>
struct Contains<T>: public std::false_type
{};
template <typename T, typename ... Pack>
struct Contains<T, T, Pack ...>: public std::true_type
{};
template <typename T, typename U, typename ... Pack>
struct Contains<T, U, Pack ...>: public Contains<T, Pack...>
{};