我需要为固定的一组类型实现一个带有虚函数模板的类结构作为模板参数(只有一个模板参数)。据我所知,这在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;从地图中提取模板参数的右指针,并在派生类中调用实现。
现在我的问题是如何使这种模式更通用,也许更短:
实例化TemplateVTable&lt;&gt;在基类(A :: myVTable的成员声明)中我需要使用技巧来传递boost::function< UserType(UserType) >
模板参数。问题是模板参数本身就是一个模板。有没有办法直接这样做而不定义额外的类&#34; functionSignature&#34;?我试过这样的事情:
TemplateVTable< template<UserType> boost::function< UserType(UserType) > > myVTable;
但它没有编译(模板参数无效)。
我在Ubuntu 12.04上使用gcc 4.3.6,启用-std = c ++ 0x以支持(不完整)C ++ 11。不幸的是,我必须坚持使用旧编译器一段时间......