简体   繁体   中英

Can I use templates to store values of different types in a map?

I have a class that represents some application event. I want to be able to set (and later retrieve) various attributes to the event. These are identified by a unique std::string label.

I was able to write the code below, which works, but, as I'm not very experienced with templates, I can't shake the feeling that there should be a better way to do this with (more) templates, and get rid of that hideous void * . Ideally, this solution will also do the attribute type checking at compile-time - but I'm not sure if that's possible.

Do you have a better way to do this?

My code (ignoring the memory leak for now):

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));
}

You can (should) replace your "Attribute" class by a type safe, variant template, such as Boost.Any or Boost.variant . Your map would be (for boost::any )

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

And yes, you would get rid of the void*, as any C++ code should!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM