我可以使用模板在地图中存储不同类型的值吗?

时间:2014-05-28 19:14:11

标签: c++ templates

我有一个代表一些应用程序事件的类。我希望能够为事件设置(并稍后检索)各种属性。这些标识由唯一的std::string标签识别。

我能够编写下面的代码,但是,由于我对模板不是很熟悉,所以我不能感觉到应该有更好的方法来使用(更多)模板,并摆脱那可怕的void *。理想情况下,此解决方案还将在编译时进行属性类型检查 - 但我不确定这是否可行。

你有更好的方法吗?

我的代码(暂时忽略内存泄漏):

class Event final
{
public:
    Event(EventType type) : type_(type) {}

    template <typename T>
    void addAttribute(std::string const &name, T value);

    template <typename T>
    void getAttribute(std::string const &name, T &value) const;

private:
    EventType type_;

    struct Attribute
    {
        std::type_index type;
        void *ptr;
    };

    std::unordered_map<std::string, Attribute> attribs_;
};

template <typename T>
inline void Event::addAttribute(std::string const &name, T value)
{
    Attribute atr = { typeid(T), new T(value) };
    auto res = attribs_.insert({ name, atr });
    if (std::get<1>(res) == false)
        throw std::runtime_error("Event::addAttribute: unordered_map insertion failed.");

}

template <typename T>
inline void Event::getAttribute(std::string const &name, T &value) const
{
    Attribute atr = attribs_.at(name);
    if (atr.type != typeid(T))
        throw std::runtime_error("Event::getAttribute: wrong attribute type requested.");
    value = *(static_cast<T *>(atr.ptr));
}

1 个答案:

答案 0 :(得分:1)

您可以(应该)使用类型安全的变体模板替换“属性”类,例如Boost.AnyBoost.variant。 你的地图将是(对于boost :: any)

std::unordered_map<std::string, boost::any> attribs_;

是的,你会摆脱void *,就像任何C ++代码一样!