简体   繁体   English

模板类多重继承编译器无法解决歧义

[英]template class multiple inheritance compiler unable to resolve ambiguity

I'll paste the relevant code only 我只会粘贴相关代码

Template class: 模板类:

template<class TMsgType, class TKeyType>
struct mapped_subscription_handler
{
protected:
    typedef std::function<void(TKeyType const &, TMsgType*)> handler_t;
    typedef std::unordered_multimap<TKeyType, subscr_obj<handler_t>> map_t;

public:
    void call(TKeyType const & key, TMsgType* msg)
    {
        //blah
    }

public:
    handler_id_t register_handler(TKeyType const & key, handler_t handler)
    {
        //blah
    }

    void unregister_handler(TKeyType key, handler_id_t id)
    {
        //blah
    }

private:
    map_t _map;
};

Implementation class: 实现类:

typedef clients::mapped_subscription_handler<NS_Snap::NS_MD::DepSnapshot, clients::header_info<NS_Snap::NS_DEF::Header>::mdid_t> depth_handler_t;
typedef clients::mapped_subscription_handler<NS_Snap::NS_MD::TrdSnapshot, clients::header_info<NS_Snap::NS_DEF::Header>::mdid_t> trd_handler_t;

class data_client 
    :public depth_handler_t,
    public trd_handler_t
{
public:

    data_client(const std::string & host, int port);
    virtual ~data_client();

    clients::handler_id_t register_on_connect(std::function<void()> connect_handler);

    using depth_handler_t::register_handler;
    using trd_handler_t::register_handler;

    using depth_handler_t::unregister_handler;
    using trd_handler_t::unregister_handler;
};

Usage: 用法:

class time_comparer
{
    internal_clients::data_client *_int_client;
    void whenever()
    {
        //Compiler complains about ambiguous call here.
        _int_client->register_handler(rep->GetId(), boost::bind(&time_comparer::on_internal_depth, this, _1, _2));
    }

    void on_internal_depth(uint64_t const & key, NS_Snap::NS_MD::DepSnapshot* depth)
    {
        //blah
    }
};

The compiler complains of ambiguous reference when I call register_handler . 当我调用register_handler时,编译器抱怨引用不明确。 Shouldn't it be able to identify which register_handler I am calling (based on boost::bind type)? 它是否应该能够识别我正在调用哪个register_handler (基于boost::bind类型)? Otherwise I have to qualify the call with the class name which is ugly. 否则,我必须使用丑陋的类名来限定通话。

EDIT: Based on input from Sebastian Redl 编辑:基于Sebastian RedlSebastian Redl输入

This simpler example encounters the same problem 这个简单的例子遇到了同样的问题

#include <iostream>
#include <functional>

template<class T>
struct test_template
{
    template<class TArg>
    void do_(T t, TArg arg)
    {
        t(arg);
    }
};

class test_class :
    public test_template<std::function<void(char*)>>,
    public test_template<std::function<void(int)>>
{
public:
    using test_template<std::function<void(char*)>>::do_;
    using test_template<std::function<void(int)>>::do_;
};

int main()
{
    test_class tc;
    tc.do_([](int x){std::cout << x << std::endl; }, 10);
    tc.do_([](char* x) {std::cout << x << std::endl; }, "what");

    return 0;
}

Is there any way around this without explicitly specifying the overload when calling? 有没有解决此问题的方法,而在调用时没有明确指定重载? ie

tc.test_template<std::function<void(int)>>::do_([](int x){std::cout << x << std::endl; }, 10);

In the simplified example, you may use SFINAE to remove template based mostly on the non function argument. 在简化的示例中,您可以使用SFINAE删除模板,该模板主要基于non function参数。

template<class T>
struct test_template
{
    template<class TArg>
    auto do_(T t, TArg arg)
    -> decltype(t(arg), void())
    {
        t(arg);
    }
};

Live demo 现场演示

std::function is very liberal in conversions to it, and in particular the standard doesn't require the conversion to be SFINAEd out if the passed function object isn't compatible. std::function在转换时非常自由,特别是如果传递的函数对象不兼容,则标准不需要将转换明确化。 So both function types appear to be constructable from the binds, which is why you get an ambiguity. 因此,这两种函数类型似乎都可以从绑定中构造出来,这就是为什么会产生歧义的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM