将方法的签名作为模板参数传递给类

8
我希望为我的项目中的数据处理类创建一个模板接口。
我可以编写如下代码:
template <class T>
class DataHandler
{
    public:
        void Process(const& T) = 0;
};

假设我这样定义一个类:
class MyClass: public DataHandler<int> 
{
    void Process(const int&) { /* Bla-bla */ }
}

现在,问题来了,我能否以某种方式定义模板接口,使其作为参数不仅接收类型T,还接收Process()函数的整个签名。
我希望实现以下功能:
class MyClass: public DataHandler<void (int&)> 
{
    void Process(const int&) { /* Bla-bla */ }
}

这是可能的吗?我知道例如boost::signal就是以这种方式接收模板参数的,但如果我理解正确,他们在那里使用了很多黑魔法。

1个回答

12

是的,你可以。但是在C++03中,你必须为每个参数数量复制/粘贴代码(不会太糟糕,因为这里你不需要为const/non-const等重载编写代码。constness已经知道!)。

template<typename FnType>
struct parm;

template<typename R, typename P1>
struct parm<R(P1)> {
  typedef R ret_type;
  typedef P1 parm1_type;
};

template <class T>
class DataHandler
{
    typedef typename parm<T>::ret_type ret_type;
    typedef typename parm<T>::parm1_type parm1_type;

    public:
        virtual ret_type Process(parm1_type t) = 0;
};

class MyClass: public DataHandler<void (const int&)> 
{
    void Process(const int&) { /* Bla-bla */ }
};

在C++0x中,您将能够编写:
template <class T>
class DataHandler;

template<typename R, typename ... P>
class DataHandler<R(P...)> 
{
    public:
        virtual R Process(P... t) = 0;
};

class MyClass: public DataHandler<void (const int&)> 
{
    void Process(const int&) { /* Bla-bla */ }
};

好多了!


现在的问题是:我们要花多少年时间才能在工作中经常使用可变参数模板。知道它能够使事情变得更简单,但这也会让人感到痛苦... - Georg Fritzsche
我应该如何更改它以支持DataProducer接口中Process()函数的多个参数?我的意思是,我想支持像DataHandler<void (int&, flot&)>这样的东西。 - Lev
@Lev,我怀疑你需要对函数类型部分特化DataHandler,以便你也能正确地得到Process函数的声明。boost::function使用预处理器生成所需的代码,但对于自己的项目和一些用途,引入这个主题几乎没有用处(在我看来),因为你可能之后不再需要它。所以只需复制/粘贴4次即可完成 :) - Johannes Schaub - litb
Johannes,您能否解释一下您在答案的前几行中所做的struct parm的预声明的含义是什么? - Lev
@Lev,它没有定义。因此如果我们执行parm<int>::parm1_type,就会出现关于应该定义parm<int>的错误。我本可以添加大括号来定义模板,然后它会说"parm1_type"类型不存在。不定义它告诉代码读者我们没有打算为那种情况提供任何意义。 - Johannes Schaub - litb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接