簡體   English   中英

在C ++中輸入地圖

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM