可变参数模板类的部分专业化方法 [英] Partially specialize methods of variadic template classes

查看:50
本文介绍了可变参数模板类的部分专业化方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个解组器,以提取存储在msgpack数组中的参数,以供调用 sigc :: signal :: emit(...)的各个参数使用。我尝试过:

I want to write an unmarshaller to extract arguments stored in a msgpack array for individual arguments to a call of sigc::signal::emit(...). I tried this:

template<class... T> class MsgpackAdapter: public MsgpackAdapterBase {
public:
    MsgpackAdapter (sigc::signal<void, T...> &sig)
            : MsgpackAdapterBase (), signal_ (sig)
    {}
protected:
    virtual void do_emit (const msgpack::object_array &mp_args) override;
private:
    sigc::signal<void, T...> signal_;
};

template<class T1>
void MsgpackAdapter<T1>::do_emit (const msgpack::object_array &mp_args)
{
    T1 a1;
    mp_args.ptr[0].convert (a1);
    signal_.emit (a1);
}

template<class T1, class T2>
void MsgpackAdapter<T1, T2>::do_emit (const msgpack::object_array &mp_args)
{
    T1 a1;
    T2 a2;
    mp_args.ptr[0].convert (a1);
    mp_args.ptr[1].convert (a2);
    signal_.emit (a1, a2);
}

,依此类推,最多可包含4个参数。但是我收到此错误消息(使用clang 3.9从vim-youcompleteme):

and so on for up to 4 arguments. But I get this error message (from vim-youcompleteme using clang 3.9):

'MsgpackAdapter<T1>::' for declaration does not refer into a class, class template or class template partial specialization  

似乎我可以进行局部专业化

It seems I can make partial specializations of the entire class:

template<class T1> class MsgpackAdapter<T1>: public MsgpackAdapterBase { ... };

但是我宁愿只对 emit 减少复制数量的方法粘贴代码。我是否错过了明显的事情?我认为主要的困难是 do_emit 不接受模板化的参数。

but I'd rather be able to specialize just the emit method to reduce the amount of copy & paste code. Have I missed something obvious? I think the main difficulty is that do_emit doesn't take templatized arguments.

另一个好奇之处是,如果我尝试在没有可变参数模板的情况下执行此操作,并使用:

Another curiosity is that if I try to do it without the variadic template, and use:

template<class T1> class MsgpackAdapter: public MsgpackAdapterBase { ... };
template<class T1, class T2> class MsgpackAdapter: public MsgpackAdapterBase { ... };

我收到一个错误,第二个类的定义与第一个类的定义冲突。这是可以理解的,但是我不知道sigc如何在没有可变参数模板的情况下管理类似的事情。

I get an error that the second class definition clashes with the first. That's understandable, but I wonder how sigc managed a similar thing without variadic templates.

推荐答案

我一直觉得这是最可维护的方法专门化成员函数的方法是服从专门化的函数对象:

I have always felt that the most maintainable way to specialise a member function is to defer to a specialised function object:

#include <iostream>

struct object_array
{
};


template<class...Ts>
struct implement_do_emit
{
    template<class This>
    void operator ()(This *that, const object_array& arg) const;
};


template<class... Ts>
struct MsgpackAdapter
{
    friend class implement_do_emit<Ts...>;

    virtual void do_emit(const object_array& mp_args)
    {
        auto impl = implement_do_emit<Ts...>();
        impl(this, mp_args);
    }

};

template<class T>
struct implement_do_emit<T>
{
    template<class This>
    void operator ()(This *that, const object_array& arg) const
    {
        std::cout << "one type version\n";
    }
};

template<class T1, class T2>
struct implement_do_emit<T1, T2>
{
    template<class This>
    void operator ()(This *that, const object_array& arg) const
    {
        std::cout << "two type version\n";
    }
};


int main()
{
    MsgpackAdapter<int> pi {};
    pi.do_emit(object_array());

    MsgpackAdapter<int, int> pii {};
    pii.do_emit(object_array());
}

这篇关于可变参数模板类的部分专业化方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆