【问题标题】:STD container inheritanceSTD 容器继承
【发布时间】:2021-03-06 22:37:04
【问题描述】:

我想声明依赖于“模式”字段的类适用于不同类型的标准容器。我该怎么做?!

class Container {
public:
    Container(int8_t initMode);
    void addPair(string name, int32_t number);
    int8_t mode;
private:
    std::_Container_base _container;
};

Container::Container(int8_t m) {
    mode = m >= 0 && m <= 2 ? m : 0;
    switch (mode) {
    case 0: 
        //_container should be Map;
        break;
    case 1:
        //_container should be Dictionary;
        break;
    case 2:
        //_container should be HashMap;
        break;
    }
}

【问题讨论】:

  • 我真的不认为你真的想这样做。如果您想要比运行时modeunion 更安全的选项,请考虑使用std::variant
  • 标准中没有std::_Container_base这样的东西,任何使用这个标识符都会使你的程序行为未定义。
  • 你的意思是假装 std::_Container_base 不存在。 stackoverflow.com/questions/9668947/…

标签: c++ std


【解决方案1】:

当您声明某个类型的变量时,该变量必须完全是该类型。您可以改为使用多态性并将_container 设为std::_Container_base*,然后通过new 将其分配为您想要的std::_Container_base 的任何子类。

我不认为std::_Container_base 是可移植的,所以你应该考虑使用你想要的容器的联合,然后根据模式切换你使用的容器。

【讨论】:

    【解决方案2】:

    您可以使用变体,甚至不需要 mode 属性,因为 std::holds_alternative&lt;MapType&gt;(_container) 可以为您提供该信息。

    template <class T>
    class Container {
    public:
    private:
      using Key = std::string;
      std::variant<
        std::map<Key,T>, 
        std::multimap<Key,T>, 
        std::unordered_map<Key,T>, 
        std::unordered_multimap<Key,T>> _container;
    }
    

    https://en.cppreference.com/w/cpp/utility/variant


    更完整的例子:

    #include <iostream>
    #include <string>
    #include <map>
    #include <stdexcept>
    #include <unordered_map>
    #include <variant>
        
    template <class T>
    class Container {
    public:
        using Key = std::string;
    
        template<class C> Container(const C& c) : _container(c) {}
        template<class C> Container(C&& c) : _container(std::move(c)) {}
    
        template<class C>
        Container& operator=(const C& c) { _container = c; return *this; }
        template<class C>
        Container& operator=(C&& c) { _container = std::move(c); return *this; }
    
        T getFirstElement(const Key& key) {
            if (!hasKey(key)) throw std::runtime_error("No such key: " + key);
            return std::visit([this, key](auto& cont){ return cont.find(key)->second; }, _container);
        }
    
        T getFirstElement(const Key& key, T or_value) noexcept {
            if (!hasKey(key)) return or_value;
            return getFirstElement(key);
        }
    
        bool hasKey(const Key& key) const {
            return std::visit([this, key](auto& cont){ return cont.count(key); }, _container) > 0;
        }
    
    private:
        std::variant<
        std::map<Key,T>, 
        std::multimap<Key,T>, 
        std::unordered_map<Key,T>, 
        std::unordered_multimap<Key,T>> _container;
    };
    
    int main()
    {   
        std::map<std::string, int> someMap {{"one", 1}, {"two", 2}};
        std::unordered_map<std::string, int> someUmap {{"one", 11}, {"two", 22}};
    
        Container<int> cont(someMap);
        std::cout << cont.getFirstElement("two") << std::endl; // 2
    
        cont = someUmap;
        std::cout << cont.getFirstElement("two") << std::endl; // 22
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多