Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 工厂模式中的模板_C++ - Fatal编程技术网

C++ 工厂模式中的模板

C++ 工厂模式中的模板,c++,C++,当我解释一个工厂模式时,该模式将枚举引入其createobject静态方法中,一位同事问我们如何使其不必在每次定义新的派生类时都添加开关案例。下面几行。我知道它不会编译(只是为了更好地表达想法) 模板 类创建者{ 公众: 静态T*createInstance(int a_ichoice){ 返回新的T(); } }; 基类{ 公众: 虚拟void SayyourName()=0; }; 类派生1:基{ 公众: void SayyourName(){ 因此,您可以在运行时将类型列表与所述列表中的索

当我解释一个工厂模式时,该模式将枚举引入其createobject静态方法中,一位同事问我们如何使其不必在每次定义新的派生类时都添加开关案例。下面几行。我知道它不会编译(只是为了更好地表达想法)

模板
类创建者{
公众:
静态T*createInstance(int a_ichoice){
返回新的T();
}
};
基类{
公众:
虚拟void SayyourName()=0;
};
类派生1:基{
公众:
void 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());
}
#包括
模板
结构类型列表{};
模板
结构索引;
模板
结构IndexOf::value
>::类型
> {
枚举{value=0};
};
模板
结构IndexOf::value
>::类型
> {
枚举{value=1+IndexOf::value};
};
模板
结构类型;
模板
结构类型{
typedef typename TypeAt::type type;
};
模板
结构类型{
typedef第一型;
};
模板
结构类型分派{
结构辅助程序{
Helper(函子常数&f_):f(f_){
函子常数&f;
模板
void Call()常量{
typedef typename TypeAt::type target_type;
f、 模板调用();
}
};
};
模板
结构运行时开关{
模板
静态布尔调用(大小、函子常数和函数){
如果(n==最大值){
f、 模板调用();
返回true;
}否则{
返回RuntimeSwitch::模板调用(n,f);
}
}
};
模板
结构运行时开关{
模板
静态布尔调用(大小、函子常数和函数){
返回false;
}
};
模板
结构动态类型分派;
模板
结构动态类型分派{
模板
静态布尔调用(大小、函子常数和函数){
typedef TypeDispatch TypeDispatch;
typedef typename typeDispatch::Helper typeCaller;
return RuntimeSwitch::Call(n,typeCaller(f));
}
};
#包括
#包括
结构测试{
std::字符串s;
Test(std::strings_uu1;):s(s_1;){
模板
void Call()常量{

std::cout模板化的
static theBase*createInstance
有什么问题吗?如果没有
开关
,如何使用
ichoice
?工厂用于在运行时选择类型;它如何知道在编译时实例化哪些模板类型?@aschepler:我想知道是否有任何通用的实现有什么方法可以通过切换来摆脱这种内务管理?@aschepler-easy:列出类型列表,为每个类型实例化
template
code,然后选择您正在使用的类型。
#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());
}