【问题标题】:Base resolution/template type deduction基本分辨率/模板类型扣除
【发布时间】:2013-11-13 07:32:54
【问题描述】:

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

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

以防万一,事件定义如下:class MouseMoveEvent: public Event&lt;MouseMoveEvent&gt;,基本模板所在的位置

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

    // ...
};

非常感谢您的帮助。

【问题讨论】:

    标签: c++ templates c++11 template-meta-programming


    【解决方案1】:

    从多个基类中查找的名称必须明确

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

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

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

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

    【讨论】:

    • 是的,我是从课外打来的。抱歉,如果原始问题中没有明确说明。
    • 我认为这个答案与问题无关,对吧?
    • @KristianD'Amato 我用来自标准的新(现在希望相关)引用更新了答案。
    • 好的,现在答案是正确的。 +1 重要的一点是:First 名称查找,然后 重载解析(参数发挥作用)。
    【解决方案2】:

    这不是特定于模板的:

    #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) {}
           ^
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-19
      • 2012-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 2015-12-09
      • 1970-01-01
      相关资源
      最近更新 更多