当我解释一个工厂模式时,它的 createobject 静态方法接受一个枚举,一位同事问我们如何才能做到这样我们就不必在每次定义新的派生类时都添加一个 switch case。下面几行的东西。我知道它不会编译(只是为了更好地表达这个想法)
template <class T>
class theCreator {
public:
static T* createInstance(int a_ichoice) {
return new T();
}
};
class theBase {
public:
virtual void SayyourName() = 0;
};
class theDerived1 : theBase {
public:
void SayyourName() {
cout << typeid(this).name();
}
};
class theDerived2 : theBase {
public:
void SayyourName() {
cout << typeid(this).name();
}
};
int main() {
theBase * p = theCreator::createInstance(1);
p->SayyourName();
}
最佳答案
因此,您可以在运行时将类型列表与索引关联到所述列表中。不确定你是否真的想要。这是我获取一个类型的示例,将其映射到类型列表的索引,调用虚函数,然后将映射反转回类型,并在基于传递的原始类型的实现中调用模板函数在:
#include <type_traits>
template<typename... Types>
struct TypeList {};
template<typename T, typename List, typename=void>
struct IndexOf;
template<typename T, typename First, typename... Types>
struct IndexOf<T, TypeList<First, Types...>,
typename std::enable_if<
std::is_same< T, First >::value
>::type
> {
enum {value = 0};
};
template<typename T, typename First, typename... Types>
struct IndexOf<T, TypeList<First, Types...>,
typename std::enable_if<
!std::is_same< T, First >::value
>::type
> {
enum {value = 1+IndexOf<T, TypeList<Types...>>::value};
};
template<size_t n, typename List>
struct TypeAt;
template<size_t n, typename First, typename... Types>
struct TypeAt<n, TypeList<First, Types...>> {
typedef typename TypeAt<n-1, TypeList<Types...>>::type type;
};
template<typename First, typename... Types>
struct TypeAt<0, TypeList<First, Types...>> {
typedef First type;
};
template<typename Functor, typename List>
struct TypeDispatch {
struct Helper {
Helper( Functor const& f_ ):f(f_) {}
Functor const& f;
template<size_t n>
void Call() const {
typedef typename TypeAt<n, List>::type target_type;
f.template Call<target_type>();
}
};
};
template<size_t max>
struct RuntimeSwitch {
template<typename Functor>
static bool Call( size_t n, Functor const& f ) {
if (n == max) {
f.template Call<max>();
return true;
} else {
return RuntimeSwitch<max-1>::template Call( n, f );
}
}
};
template<>
struct RuntimeSwitch< size_t(-1) > {
template<typename Functor>
static bool Call( size_t n, Functor const& f ) {
return false;
}
};
template<typename List>
struct DynamicTypeDispatch;
template<typename... Types>
struct DynamicTypeDispatch<TypeList<Types...>> {
template<typename Functor>
static bool Call( size_t n, Functor const& f ) {
typedef TypeDispatch<Functor, TypeList<Types...>> typeDispatch;
typedef typename typeDispatch::Helper typeCaller;
return RuntimeSwitch<sizeof...(Types)-1>::Call(n, typeCaller(f));
}
};
#include <iostream>
#include <string>
struct Test {
std::string s;
Test( std::string s_ ):s(s_) {}
template<typename T>
void Call() const {
std::cout << sizeof(T) << " == " << s.c_str() << " I hope\n";
}
};
struct Test2Base {
typedef TypeList<int, double, char> TestList;
virtual void Dispatch( size_t n ) = 0;
template<typename T>
void Test(T const& unused) {
Dispatch( IndexOf<T, TestList>::value );
}
};
template<typename Child>
struct Test2CRTP: Test2Base {
Child* self() { return static_cast<Child*>(this);}
Child const* self() const { return static_cast<Child const*>(this); }
template<typename T>
void Call() const {
self()->template TestImpl<T>();
}
virtual void Dispatch( size_t n ) {
DynamicTypeDispatch<Test2Base::TestList>::Call( n, *this );
}
};
struct Test2Impl: Test2CRTP<Test2Impl> {
template<typename T>
void TestImpl() const {
std::cout << T(256.1) << "\n";
}
};
int main()
{
typedef TypeList<int, double> TestList;
DynamicTypeDispatch<TestList>::Call( 0, Test("4") );
DynamicTypeDispatch<TestList>::Call( 1, Test("8") );
Test2Impl test2;
test2.Test(int());
test2.Test(char());
test2.Test(double());
}
现在,你真的想做这么重的事情,而不是维护一个 enum
吗?
但这是可能的。 :)
关于c++ - 工厂模式中的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14653072/