Неоднозначный доступ к функции-члену шаблона базового класса - PullRequest
8 голосов
/ 26 апреля 2010

В Visual Studio 2008 компилятор не может разрешить вызов SetCustomer в _tmain ниже и сделать его однозначным:

template <typename TConsumer>
struct Producer
{
    void SetConsumer(TConsumer* consumer) { consumer_ = consumer; }

    TConsumer* consumer_;
};

struct AppleConsumer
{
};

struct MeatConsumer
{
};

struct ShillyShallyProducer : public Producer<AppleConsumer>,
                              public Producer<MeatConsumer>
{
};

int _tmain(int argc, _TCHAR* argv[])
{
    ShillyShallyProducer producer;
    AppleConsumer consumer;
    producer.SetConsumer(&consumer);   //  <--- Ambiguous call!!

    return 0;
}

Это ошибка компиляции:

// error C2385: ambiguous access of 'SetConsumer'
//    could be the 'SetConsumer' in base 'Producer<AppleConsumer>'
//    or could be the 'SetConsumer' in base 'Producer<MeatConsumer>'

Я думал, что механизм поиска аргументов шаблона будет достаточно умен, чтобы вывести правильную базу Producer. Почему не так?

Я мог бы обойти это, изменив Producer на

template <typename TConsumer>
struct Producer
{
    template <typename TConsumer2>
    void SetConsumer(TConsumer2* consumer) { consumer_ = consumer; }

    TConsumer* consumer_;
};

и звоните SetConsumer как

    producer.SetConsumer<AppleConsumer>(&consumer);   // Unambiguous call!!

но было бы лучше, если бы мне не пришлось ...

Ответы [ 2 ]

13 голосов
/ 26 апреля 2010

Я думал, что механизм поиска аргументов шаблона будет достаточно умен, чтобы определить правильный базовый источник.

Это не имеет отношения к шаблонам, это происходит из-за использования нескольких базовых классов - поиск имени уже неоднозначен, и разрешение перегрузки происходит только после этого.

Упрощенный пример будет следующим:

struct A { void f()    {} };
struct B { void f(int) {} };
struct C : A, B {};

C c;
c.f(1); // ambiguous

Обходные пути явно квалифицируют вызов или вводят функции в область видимости производных классов:

 struct ShillyShallyProducer : public Producer<AppleConsumer>,
                               public Producer<MeatConsumer>
 {
     using Producer<AppleConsumer>::SetConsumer;
     using Producer<MeatConsumer >::SetConsumer;
 };
2 голосов
/ 26 апреля 2010

Вы можете просто использовать явную квалификацию в своем вызове функции. Вместо:

producer.SetConsumer(&consumer);

попробовать:

producer.Producer<AppleConsumer>::SetConsumer(&consumer);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...