我不确定模板类型演绎是否会在这里加入战斗。但让我解释一下。
我有一个模板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
。
hellRaiserObject->Trigger(MouseMoveEvent(11, -4));
假设对象派生自EventProducer<MouseMoveEvent>
和EventProducer<MouseButtonEvent>
?hellRaiserObject->Subscribe(mouseCallback);
。我理解在这里推断出类型可能有点困难,但mouseCallback
有一个特定的签名,可以与模板特化进行比较,我认为它只适合其中一个。以防它有所不同,事件的定义如下:class MouseMoveEvent: public Event<MouseMoveEvent>
,其中基本模板是
template <typename TEventArgs>
class Event
{
public:
typedef TEventArgs EventArgs;
typedef void HandlerSignature(TEventArgs&);
// ...
};
非常感谢。
答案 0 :(得分:3)
来自多个基类的名称查找必须是明确的
10.2会员名称查找[class.member.lookup]
1会员名称查找确定名称的含义(id-expression) 在一个范围内(3.3.7)。名称查找可能导致歧义 该程序的格式错误。
标准的这一部分中有很多关于如何合并各种基类的名称的技术细节,但最后,如果出现歧义,程序就会形成错误。因此,您需要限定您的名字才能解决此问题。
请注意,各种函数的最佳匹配签名将在重载解析期间发挥作用,但只有在成功且明确的名称查找之后才会发生。
答案 1 :(得分: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) {}
^