如何在C ++中实现(排序)模板化虚函数调用

时间:2016-02-29 15:22:38

标签: c++ templates boost

我需要为固定的一组类型实现一个带有虚函数模板的类结构作为模板参数(只有一个模板参数)。据我所知,这在C ++中是不可能的,因为没有办法告诉编译器它应该在vtable中保留条目的模板参数。

我找到了一个基于boost :: fusion的模式,它似乎实现了正确的行为,但我想知道这是否可以进一步推广,最好不要过分依赖宏。

首先,这是开始的代码:

#include <iostream>

#include <boost/fusion/include/at_key.hpp>
#include <boost/fusion/container/map.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

template< template<typename> class Signature >
class TemplateVTable {
  public:
    boost::fusion::map<
        boost::fusion::pair<int, Signature<int> >,
        boost::fusion::pair<double, Signature<double> >
     > table;
};

class A {
  public:
    template<typename UserType>
    UserType doSomething(UserType arg) {
        return boost::fusion::at_key<UserType>(myVTable.table)(arg);
    }

    template<typename UserType>
    class functionSignature : public boost::function< UserType(UserType) > {
      public:
        boost::function< UserType(UserType) >& operator=(const boost::function< UserType(UserType) > &rhs) {
          return boost::function< UserType(UserType) >::operator=(rhs);
        }
    };

    TemplateVTable< functionSignature > myVTable;
};


class B : public A {
  public:

    class FillVTable {
      public:
        FillVTable(B *_object) : object(_object) {}

        template<typename T>
        void operator()(T& pair) const {
          pair.second = boost::bind(&B::doSomething<typename T::first_type>, object, _1);
        }

    private:

        B *object;
    };

    B() {
      boost::fusion::for_each(myVTable.table, FillVTable(this));
    }

    template<typename UserType>
    UserType doSomething(UserType arg) {
        return arg+offset;
    }

    int offset;

};

int main(int argc, char* argv[]) {   
    B b;
    b.offset = 3;

    A *a = &b;

    std::cout << a->doSomething<int>(5.3) << std::endl;
    std::cout << a->doSomething<double>(5.3) << std::endl;

    return 0;
}

此代码使用gcc 4.6.3编译并按预期输出:

8
8.3

只是为了解释它是如何工作的:boost :: fusion :: map在构造时由派生类填充,并带有指向其模板化成员函数的指针&#34; doSomething&#34;对于地图中的所有类型(请参阅for_each语句和FillVTable函数类)。在基类中,模板化成员函数&#34; doSomthing&#34;从地图中提取模板参数的右指针,并在派生类中调用实现。

现在我的问题是如何使这种模式更通用,也许更短:

  1. 实例化TemplateVTable&lt;&gt;在基类(A :: myVTable的成员声明)中我需要使用技巧来传递boost::function< UserType(UserType) >模板参数。问题是模板参数本身就是一个模板。有没有办法直接这样做而不定义额外的类&#34; functionSignature&#34;?我试过这样的事情:

    TemplateVTable< template<UserType> boost::function< UserType(UserType) > > myVTable;
    

    但它没有编译(模板参数无效)。

  2. 为了使它更通用,我想从给定的类型列表以某种方式生成类TemplateVTable,例如以模板参数的形式或作为mpl :: vector左右。这有点可能吗?我可以想象使用一些级联宏来为有限数量的类型执行此操作,但是使用例如可变参数模板参数会更好,因为它不会限制类型的数量。
  3. 是否有可能用lambda表达式替换仿函数类FillVTable?它必须是模板化的lambda表达式,但我在文档中找不到任何相关内容。
  4. 我们可以为多个模板参数扩展吗?
  5. 我在Ubuntu 12.04上使用gcc 4.3.6,启用-std = c ++ 0x以支持(不完整)C ++ 11。不幸的是,我必须坚持使用旧编译器一段时间......

0 个答案:

没有答案