C ++ 11: Klassenmitglied in Mehrfachvererbung disambiguieren

Angenommen, ich habe diese variadische Basisklassenvorlage:

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";
    }
};

Dasfoo() member kann nur aufgerufen werden, wenn sein Template-Parameter mit mindestens einem der Parameter von @ übereinstimBase (Die Implementierung vonContains ist unten in diesem Beitrag aufgeführt):

Base<int, char>().foo<int>(); // fine
Base<int, char>().foo<void>(); // error

Nun definiere ich eine abgeleitete Klasse, die zweimal von Base erbt, mit nicht überlappende Mengen von Typen:

struct Derived: public Base<int, char>,
                public Base<double, void>
{};

Ich hatte gehofft, dass beim Aufruf von z. B.

Derived().foo<int>();

Der Compiler würde herausfinden, welche Basisklasse verwendet werden soll, da es sich um eine SFINAE-Klasse handelt, die @ nicht enthälint. Sowohl GCC 4.9 als auch Clang 3.5 beschweren sich jedoch über einen mehrdeutigen Anruf.

Meine Frage ist dann zweifach:

Warum kann der Compiler diese Mehrdeutigkeit nicht beheben (allgemeines Interesse)?Was kann ich tun, um diese Arbeit zu machen, ohne schreiben zu müssenDerived().Base<int, char>::foo<int>();? BEARBEITEN GuyGreer hat mir gezeigt, dass der Aufruf eindeutig ist, wenn ich zwei using-Deklarationen hinzufüge. Da ich jedoch die Basisklasse bereitstelle, von der der Benutzer erben kann, ist dies keine ideale Lösung. Ich möchte nicht, dass meine Benutzer diese Deklarationen (die für große Typlisten sehr ausführlich und sich wiederholend sein können) zu ihren abgeleiteten Klassen hinzufügen müssen, wenn dies überhaupt möglich is

Implementierung vonContains:

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...>
{};

Antworten auf die Frage(4)

Ihre Antwort auf die Frage