2013-02-14 97 views
4

我有以下類使用3個不同的地圖:鍵總是字符串,而值可能是字符串,整數或浮點數。typeid()面向對象的設計替代

class MyMaps 
{ 

public: 

    template<typename T> void addKey(const std::string& key); 
    void addValue(const std::string& key, const std::string& value); 
    void addValue(const std::string& key, int value); 
    void addValue(const std::string& key, float value); 

private: 

    std::map<std::string, std::string> stringFields;    
    std::map<std::string, int> intFields;      
    std::map<std::string, float> floatFields;     
}; 

addValue()功能只需添加一對新的相關地圖。什麼我工作是addKey()模板函數:

/** Add only a key, the related value is a default one and is specified by template parameter T. */ 

template<typename T> 
void MyMaps::addKey(const string& key) 
{  
    if (typeid(T) == typeid(string)) 
    { 
     stringFields.insert(pair<string, string>(key, string())); 
    } 

    else if (typeid(T) == typeid(int)) 
    { 
     intFields.insert(pair<string, int>(key, int()));; 
    } 

    else if (typeid(T) == typeid(float)) 
    { 
     floatFields.insert(pair<string, float>(key, float())); 
    } 
} 

基本上,我使用templatetypeid(),因爲我不喜歡這樣的替代方案,依靠類型中,函數名

void MyMaps::addStringKey(const string& key) 
{ 
    stringFields.insert(pair<string, string>(key, string())); 
} 

void MyMaps::addIntKey(const string& key) 
{ 
    intFields.insert(pair<string, int>(key, int())); 
} 

void MyMaps::addFloatKey(const string& key) 
{ 
    floatFields.insert(pair<string, float>(key, float())); 
} 

第一addKey()版本似乎的工作,但我不知道是否有一個更優雅的解決方案。也許我錯過了一些面向對象的設計概念,在這種情況下可能會有所幫助?

在此先感謝。

回答

6

這是模板專業化完美契合:

template<> 
void MyMaps::addKey<string>(const string& key) 
{  
    stringFields.insert(pair<string, string>(key, string())); 
} 

template<> 
void MyMaps::addKey<int>(const int& key) 
{ 
    intFields.insert(pair<string, int>(key, int()));; 
} 

template<> 
void MyMaps::addKey<float>(const float& key) 
{ 
    floatFields.insert(pair<string, float>(key, float())); 
} 

編輯:對於語法/關於模板特更多信息閱讀:Template Specialization and Partial Template Specialization

或者更好的是,如果提升是一個選項,如果鍵對於所有3個獨特的地圖,你有3個不同的地圖,只是爲了能夠存儲它們,那麼可以考慮使用boost::variant

typedef boost::variant<string, int, float> ValueType; 

class MyMap 
{ 

public: 
    typedef std::map<std::string, ValueType> MapType; 
    template<typename T> void addKey(const std::string& key, T &val) 
    { 
     ValueType varVal= val; 
     allFields.insert(MapType::value_type(key, varVal)); 
    } 

private: 

    MapType allFields;        
}; 
+0

我不確定所有的鍵都不一樣。所以模板專業化可能是我正在尋找的。唯一的問題是,我不知道我必須在我的課堂上聲明什麼和正確的語法。 – eang 2013-02-14 20:55:14

+1

刪除語法不會更改。我給出的實現是定義/實現語法 – eladidan 2013-02-14 21:06:08

0

可能不是你想要的,因爲它是一種不同的方法,但你可以使用變體的地圖。您可以定義boost::variant以僅保存字符串,int或float。

eladidan擊敗了我,我不知道如何刪除答案。

+0

擊敗你:) – eladidan 2013-02-14 19:11:15

+0

我會在下次給你! :) – Aeluned 2013-02-14 19:11:44

2

你的問題詢問兩兩件事:

  1. 真正的問題,製作一個鍵值地圖或字典,使用不同類型的價值觀,同樣收藏。

  2. 而且,一個潛在的解決方案,應用「typeid」功能。

更多參考約 「的typeid」:

http://en.cppreference.com/w/cpp/language/typeid

對象(和類)方向是偉大的,但是,有時你可能會想將它與其他範式混合。

「指針」呢?

指針允許不同類型,被視爲相同的簡單類型。

密鑰值字典集合,它存儲一個字符串鍵和一個指針值,指針可能是整數,字符串或對象。

或者更具體。 「值」可以是一個元組,其中第一個字段(可能是一個枚舉類型)表示值的實際類型。而且,「價值」的第二個領域是指向真實領域的指針或變體。

使用 「聯盟」(又名 「變異體」)的第一個建議,沒有指針:

#include <string> 
#include <typeinfo> 

union ValueUnion 
{ 
    int AsInt, 
    float AsFloat, 
    std::string& AsStr 
}; 

struct ValueType 
{ 
    std::type_info Id, 
    ValueUnion Value 
}; 

class MyMaps 
{ 
public: 
    template<typename T> void addKey(const std::string& key); 
    void addValue(const std::string& key, const std::string& value); 
    void addValue(const std::string& key, int value); 
    void addValue(const std::string& key, float value); 
private: 

    std::map<std::string, ValueType> Fields;  
}; 

或者,使用指針:

#include <string> 
#include <typeinfo> 

struct ValueType 
{ 
    std::type_info Id, 
    void* Value 
}; 

class MyMaps 
{ 
public: 
    template<typename T> void addKey(const std::string& key); 
    void addValue(const std::string& key, const std::string& value); 
    void addValue(const std::string& key, int value); 
    void addValue(const std::string& key, float value); 
private: 
    std::map<std::string, ValueType> Fields; 
}; 

我已經看到了這種 「模式」 了好幾次,我稱之爲「Key-Value-Type」集合。

注意:STL的經驗並不多,你確定「std :: map」, 是否合適?

只是我2美分。