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

时间:2014-10-16 07:53:03

标签: c++ templates multiple-inheritance

我只会粘贴相关代码

模板类:

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

实施班:

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

用法:

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

当我调用register_handler时,编译器会抱怨含糊不清的引用。我不能识别我正在呼叫的register_handler(基于boost::bind类型)吗?否则,我必须使用丑陋的类名限定调用。

编辑: 基于Sebastian Redl

的输入

这个更简单的例子遇到了同样的问题

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

有没有办法在没有明确指定调用时的重载?即

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

2 个答案:

答案 0 :(得分:2)

在简化示例中,您可以使用SFINAE来删除主要基于非函数参数的模板。

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

Live demo

答案 1 :(得分:0)

std::function对它的转换非常宽松,特别是如果传递的函数对象不兼容,标准不要求转换为SFINAEd。因此,两种函数类型似乎都可以从绑定中构造出来,这就是为什么会出现歧义。