对基类模板成员函数的不明确访问

Joh*_*ell 8 c++ templates

在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;
}
Run Code Online (Sandbox Code Playgroud)

这是编译错误:

// error C2385: ambiguous access of 'SetConsumer'
//    could be the 'SetConsumer' in base 'Producer<AppleConsumer>'
//    or could be the 'SetConsumer' in base 'Producer<MeatConsumer>'
Run Code Online (Sandbox Code Playgroud)

我认为模板参数查找机制足够聪明,可以推断出正确的基础Producer.为什么不呢?

我可以通过改变Producer来解决这个问题

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

    TConsumer* consumer_;
};
Run Code Online (Sandbox Code Playgroud)

并呼吁SetConsumer

    producer.SetConsumer<AppleConsumer>(&consumer);   // Unambiguous call!!
Run Code Online (Sandbox Code Playgroud)

但如果我不必......那就更好了......

Geo*_*che 13

我认为模板参数查找机制足够聪明,可以推断出正确的基本生产者.

这与模板无关,它来自于使用多个基类 - 名称查找已经不明确,并且重载解析仅在此之后发生.

一个简化的例子如下:

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

C c;
c.f(1); // ambiguous
Run Code Online (Sandbox Code Playgroud)

变通方法显式限定了调用或将函数引入派生类范围:

 struct ShillyShallyProducer : public Producer<AppleConsumer>,
                               public Producer<MeatConsumer>
 {
     using Producer<AppleConsumer>::SetConsumer;
     using Producer<MeatConsumer >::SetConsumer;
 };
Run Code Online (Sandbox Code Playgroud)