[英]Type map in C++
我將從一個導致實際問題的上下文開始。
我正在嘗試建立一個類,其每個實例將管理如何將數據綁定到對象中。 該類最好包含方法:
class DataManager {
Object CreateObject();
void DestoryObject();
template<typename DataType>
DataType* AddDataToObject(Object o)
template<typename DataType>
DataType* GetDataForObject(Object o)
template<typename DataType>
void RemoveDataFromObject(Object o)
};
上面代碼中的對象只是一些標識符-此時為int,不包含任何數據或方法(這不應更改)。 上面使用的DataType基本上可以是任何類,但是一般情況是這只是一個沒有方法的結構。 可以用作DataType的事物的完整列表在編譯時是已知的,但不應進行編碼,因為它經常更改。
我嘗試實現的兩個目標是:-可維護性/速度-用戶應該能夠在不修改此代碼的情況下添加新的DataType結構-速度-應該盡可能快:)
現在,到目前為止,我最好的想法是創建一個容器類:
class ContainerBase;
template<typename DataType>
class DataTypeContainer : ContainerBase;
數據結構將類似於:
map< DataTypeType, map< Object, ContainerBase* > >
母豬怎么能做到這一點? 會對boost :: mpl :: map幫助有幫助嗎?
從本質上講,應該可以這樣做,因為所有DataType在編譯時都是已知的。
我認為您需要std :: tuple c ++ 11或使用boost :: tuple for c ++ 03
template<typename T>
struct Entry{
T t;
};
int main(int argc, char **argv) {
std::tuple< int, float, double, Entry<int> > objects;
std::get<0>(objects) = 3;
std::get<3>(objects).t = 5;
//
utils::get< Entry<int> >(object).t = 5;
return 0;
}
按類型獲取可以像下面這樣實現: https : //github.com/alekstheod/tnnlib/blob/master/src/Utilities/Utilities/MPL/Tuple.h
您可以使用以下類型之間的映射創建一個元組:
template < std::size_t sz, typename... Types >
struct TypeMap {
TypeMap (std::array< std::tuple< Types... >, sz > m) : mapping (m) {
}
std::array< std::tuple< Types... >, sz > mapping;
};
然后指定一個要轉換的函數
template < typename To, typename From, std::size_t sz, typename... T >
To convert (From from, TypeMap< sz, T... > m) {
for (auto entry : m.mapping) {
if (utils::get< From > (entry) == from) {
return utils::get< To > (entry); //Tricky part here
}
}
throw std::logic_error ("No entry in the typemap");
}
然后指定映射
const auto map = TypeMap{{std::make_tuple (red, "red", 1),
std::make_tuple (green, "green", 2),
std::make_tuple (blue, "blue", 3)}};
最后,您可以調用您的convert函數並將任何類型轉換為任何其他類型;)
在這里查看我的文章: https : //cpptelepathy.wordpress.com/
您將需要此文件https://github.com/alekstheod/tnnlib/blob/master/src/Utilities/MPL/Tuple.h
對於util :: get
class DataManager {
struct internal_base { virtual ~internal_base() {} };
template<typename T> struct internal_data : public internal_base {
T t;
};
boost::unordered_map<Object, boost::unordered_map<std::string, boost::unique_ptr<internal_base>>> data;
public:
Object CreateObject() { return Object(); }
void DestroyObject(Object o) { data.erase(o); }
template<typename DataType> DataType* AddDataToObject(Object o, std::string name) {
internal_data<T>* ptr = new internal_data<T>();
data[o][name] = ptr;
return &ptr->t;
}
template<typename DataType> DataType* GetDataForObject(Object o, std::string name) {
internal_base* ptr = data[o][name].get();
if (internal_data<DataType>* dptr = dynamic_cast<internal_data<DataType>*>(ptr)) {
return &dptr->t;
else
return 0;
}
void RemoveDataFromObject(Object o, std::string name) {
data[o][name] = 0;
}
};
這段代碼做出了一些假設,例如Object類型的默認構造,並且它是可哈希的。 但是修改起來應該不會太困難。 如果只希望與特定對象關聯的每種類型的一個數據成員,則要獲得定義的行為將非常困難,因為您不能依賴RTTI為每種可能的DataType返回唯一的名稱。
如果要等效於從類型到值的map
,並且它可以是全局的,則可以使用static
成員:
template <typename T>
struct DataManager {
static std::map<void*, Object> this_type_map;
};
加的適當的定義DataManager<T>::this_type_map
為的各種值T
(但這些定義並不需要是相同的源文件中)。 之后,您可以使用(void*)(new int)
創建類型映射對象,使用delete (int*)(m)
釋放它們,並使用DataManager<T>::this_type_map[m]
查找對象m
和類型T
的對象DataManager<T>::this_type_map[m]
。 當然,您可能希望將它們包裝在函數或對象中。 請注意, map
的值類型可以具有與Object
不同的類型,包括(使用模板特殊化)類型映射中的每種鍵類型都具有不同的值類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.