3

我不确定模板类型扣除是否会在此处加入竞争。但让我解释一下。

我有一个模板class EventProducer,引发事件的对象从该模板派生一次,每个事件类型一次,这样我就可以拥有这样的东西:class HellRaiser: public EventProducer<MouseMoveEvent>, public EventProducer<MouseButtonEvent>. 这似乎工作得很好,除了EventProducer在通过派生类的对象调用时必须使用基类型限定调用。但是编译器不应该自动推导出基数EventProducer吗?

这是定义:

template <typename TEvent>
class EventProducer
{
public:
    typedef function<typename TEvent::HandlerSignature> HandlerFunction;

    //  Methods.
    connection Subscribe(const HandlerFunction& callback);
    void Trigger(TEvent& event);

protected:
    // ...
};

TEvent::HandlerSignature事件类中定义的位置。

  1. 为什么这个调用模棱两可:hellRaiserObject->Trigger(MouseMoveEvent(11, -4));假设对象派生自EventProducer<MouseMoveEvent>and EventProducer<MouseButtonEvent>
  2. 我可以做些什么来帮助编译器决定调用哪个,而不明确指定基数吗?
  3. 这个调用也会发生同样的情况:hellRaiserObject->Subscribe(mouseCallback);. 我知道在这里推断类型可能有点困难,但mouseCallback有一个可以与模板专业化进行比较的特定签名,我认为它只适合其中一个。

以防万一它有所作为,事件定义如下:class MouseMoveEvent: public Event<MouseMoveEvent>,其中基本模板是

template <typename TEventArgs>
class Event
{
public:
    typedef TEventArgs EventArgs;
    typedef void HandlerSignature(TEventArgs&);

    // ...
};

非常感谢帮助。

4

2 回答 2

3

来自多个基类的名称查找必须是明确的

10.2 成员名称查找[class.member.lookup]

1 成员名称查找确定类范围(3.3.7)中名称(id-expression)的含义。名称查找可能会导致歧义,在这种情况下程序格式错误。

标准的该部分中有很多关于如何合并来自各种基类的名称的技术细节,但最终,如果出现歧义,则程序格式错误。因此,您需要限定您的姓名才能解决此问题。

请注意,各种函数的最佳匹配签名将在重载解析期间发挥作用,但这仅在成功且明确的名称查找之后才会发生。

于 2013-11-13T07:57:59.987 回答
0

这不是特定于模板:

#include <string>

class HandlerString
{
public:
    void Handle(const std::string& event) {}
};

class HandlerInt
{
public:
    void Handle(int event) {}
};

class ConcreteHandler : public HandlerString, public HandlerInt {};

int main(int argc, char const *argv[])
{
    ConcreteHandler handler;

    handler.Handle(std::string("foo"));
    handler.Handle(1);
    return 0;
}

g++ 4.8.1 的输出:

test.cpp: In function 'int main(int, const char**)':
test.cpp:21:10: error: request for member 'Handle' is ambiguous
  handler.Handle(std::string("foo"));
          ^
test.cpp:12:7: note: candidates are: void HandlerInt::Handle(int)
  void Handle(int event) {}
       ^
test.cpp:6:7: note:                 void HandlerString::Handle(const string&)
  void Handle(const std::string& event) {}
       ^
test.cpp:22:10: error: request for member 'Handle' is ambiguous
  handler.Handle(1);
          ^
test.cpp:12:7: note: candidates are: void HandlerInt::Handle(int)
  void Handle(int event) {}
       ^
test.cpp:6:7: note:                 void HandlerString::Handle(const string&)
  void Handle(const std::string& event) {}
       ^
于 2013-11-13T15:16:10.570 回答