2013-02-14 66 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美分。