【问题标题】:Ambiguous access to base class template member function对基类模板成员函数的模糊访问
【发布时间】:2011-02-12 09:05:24
【问题描述】:

在 Visual Studio 2008 中,编译器无法解析下面_tmain 中对SetCustomer 的调用并使其明确:

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!!

但如果我不必这样做会更好......

【问题讨论】:

  • 我只想指出,在您提出的解决方法中,您不需要调用SetConsumer&lt;AppleConsumer&gt;(&amp;consumer)SetConsumer(&amp;consumer) 就足够了(并正确推断出模板参数)。
  • @sbk:不,不会。我在发布之前尝试过,现在再次确定。仍然模棱两可。

标签: c++ templates


【解决方案1】:

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

这与模板无关,它来自于使用多个基类 - 名称查找已经是模棱两可的,重载决议只发生在此之后。

一个简化的例子如下:

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

【讨论】:

  • @gf: "将函数引入派生类范围" - 这是一个很好的解决方案,因为我不想在每次添加新产品时都更改生产者客户的呼叫站点。可爱 - 谢谢!
【解决方案2】:

您可以在函数调用中使用显式限定。而不是:

producer.SetConsumer(&consumer);

尝试:

producer.Producer<AppleConsumer>::SetConsumer(&consumer);

【讨论】:

    猜你喜欢
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多