2017-07-06 59 views
1

我目前工作的一個項目中,我的應用程序的客戶端部分必須能夠在服務器上創建自定義的模板類。服務器部分必須跟蹤這些創建的類,並且必須記住類已經被實例化的類型。問題是,在我的應用程序中有大約36個不同的類模板組合。我目前正努力追蹤集合中的這些不同類型,而不會丟失關於我的實例的信息。商店不同的模板類在一個容器中,而不會丟失信息,它的類型

我目前使用的是這樣的:

#include <memory> 
#include <type_traits> 
#include <vector> 

enum class data_type : std::uint8_t { 
    type_int = 1, 
    type_float, 
    type_double 
}; 

enum class class_type : std:: uint8_t { 
    type_A = 1, 
    type_B 
}; 

struct X { 
    virtual data_type get_data_type() = 0; 
    virtual class_type get_class_type() = 0; 
}; 

template <typename T> 
struct A : X { 
    data_type get_data_type() override 
    { 
     if (std::is_same<T, int>::value) { 
      return data_type::type_int; 
     } else if (std::is_same<T, float>::value) { 
      return data_type::type_float; 
     } else if (std::is_same<T, double>::value) { 
      return data_type::type_double; 
     } else { 
      /* ... */ 
     } 
    } 

    class_type get_class_type() override 
    { 
     return class_type::type_A; 
    } 
}; 

template <typename T> 
struct B : X { 
    data_type get_data_type() override 
    { 
     if (std::is_same<T, int>::value) { 
      return data_type::type_int; 
     } else if (std::is_same<T, float>::value) { 
      return data_type::type_float; 
     } else if (std::is_same<T, double>::value) { 
      return data_type::type_double; 
     } else { 
      /* ... */ 
     } 
    } 

    class_type get_class_type() override 
    { 
     return class_type::type_B; 
    } 
}; 

struct Storage { 

    template <typename T, template <typename> class Class> 
    void create() { 
     Class<T>* t = new Class<T>(); 
     _classes.push_back(std::unique_ptr<X>(t)); 
    } 

    std::vector<std::unique_ptr<X>> _classes; 
}; 

,但還是我不知道這是否是要走的路,如果有一個更優雅的方式。在這裏,我將不得不總是通過enum s開關來獲得完整的類型我的存儲類的,是這樣的:提前

switch(_classes.front()->get_class_type()) { 
case class_type::type_A: 
{ 
    switch(_classes.front()->get_data_type()) { 
    case data_type::type_int: 
    { 
     /* I finally know that it is A<int> */ 
    } 
/* ... */ 

感謝。

+0

'的std :: variant'? – Klaus

+1

會[這裏](https://wandbox.org/permlink/W1Dk1C4A3ubC04mS)爲你工作? – skypjack

+0

真的很有幫助。感謝您的輸入@skypjack – reedts

回答

3

如果if constexpr長相醜陋到你,那麼你可以用一個手卷訪問者類代替它,以及你可以考慮使用std::variantstd::visit模式

auto var = std::variant<int, float, double>{}; 
// assign var to value 
std::visit([](auto& value) { 
    using Type = std::decay_t<decltype(value)>; 
    if constexpr (std::is_same<Type, int>{}) { 
     // is an int 
    } else if (std::is_same<Type, float>{}) { 
     // is float 
    } else if (std::is_same<Type, double>{}) { 
     // is double 
    } 
}, var); 

class Visitor { 
public: 
    void operator()(int& value) { ... } 
    void operator()(float& value) { ... } 
    void operator()(double& value) { ... } 
}; 

auto var = std::variant<int, float, double>{}; 
// assign var to value 
std::visit(Visitor{}, var); 
+0

我認爲我有你的想法,但我不確定它是否適用,如果我有2個「模板」級別。所以,在我來說,我將有這樣的事情(?): '的std ::向量<性病::變種,A ,A >' **編輯**:請糾正我,如果我米誤解 – reedts

+1

@reedts如果你有'A'實例化'int','double'和'float'您只需更換'is_same'與比較'一個','一個'和'一個'代替 – Curious

+0

謝謝,這真的很有幫助!我想這個設計與@skypjack – reedts

2

正如評論的問題提到的,這是一個可行的方法,可以幫助:

#include<vector> 
#include<memory> 

struct Counter { 
    static int next() { 
     static int v = 0; 
     return v++; 
    } 
}; 

template<typename> 
struct Type: Counter { 
    static int value() { 
     static const int v = Counter::next(); 
     return v; 
    } 
}; 

struct X { 
    virtual int get_data_type() = 0; 
    virtual int get_class_type() = 0; 
}; 

template <typename T> 
struct A : X { 
    int get_data_type() override { 
     return Type<T>::value(); 
    } 

    int get_class_type() override { 
     return Type<A<T>>::value(); 
    } 
}; 

template <typename T> 
struct B : X { 
    int get_data_type() override { 
     return Type<T>::value(); 
    } 

    int get_class_type() override { 
     return Type<B<T>>::value(); 
    } 
}; 

struct Storage { 
    template <typename T, template <typename> class Class> 
    void create() { 
     Class<T>* t = new Class<T>(); 
     _classes.push_back(std::unique_ptr<X>(t)); 
    } 

    std::vector<std::unique_ptr<X>> _classes; 
}; 

int main() { 
    Storage s; 
    s.create<int, A>(); 

    if(Type<int>::value() == s._classes.front()->get_class_type()) { 
     //... 
    }; 
} 

看到它在wandbox運行。

相關問題