How can I improve this design that forces me to declare a member function const and declare variables mutable?

前端 未结 3 1133
情深已故
情深已故 2020-12-20 20:26

For some reason I am iterating over elements of a class in an std::set and would like to slightly modify the keys, knowing that the order will be unchanged.

3条回答
  •  旧时难觅i
    2020-12-20 20:49

    One possibility might be to factor out the value part of Foo in a pimpl.

    class Element
    {
    public:
    
        Element(int key, int value);
    
        Element( const Element& el );
        Element( Element&& el );
    
        ~Element();
    
        bool operator < (const Element& o) const;
    
        void incrementValue() const;
        int  getValue() const;
    
    private:
    
        Element& operator=(const Element& );
        Element& operator=( Element&& el );
    
        struct Key
        {
            Key( const int key ) : m_KeyValue( key )
            {
            };
    
            const int m_KeyValue;
        };
    
        struct Value;
    
        const   Key                 m_Key;
        std::unique_ptr      m_Value;
    
    };
    
    struct Element::Value
    {
        Value( int val ) : value(val)
        {
    
        }
    
        int value;
    };
    
    Element::Element(int key, int value) : 
        m_Key(key),
        m_Value( new Element::Value(value) )
    {
    
    }
    
    Element::~Element()
    {
    
    }
    
    Element::Element( const Element& el ) : 
        m_Key( el.m_Key ),
        m_Value( new Element::Value( *el.m_Value ) )
    {
    
    }
    
    Element::Element( Element&& el ) : 
        m_Key(el.m_Key)
    {
        m_Value = std::move(el.m_Value);
        el.m_Value.release();
    }
    
    bool Element::operator < (const Element& o) const 
    { 
        return m_Key.m_KeyValue < o.m_Key.m_KeyValue; 
    }
    
    void Element::incrementValue() const
    {
        m_Value->value++;
    }
    
    int  
    Element::getValue() const
    {
        return m_Value->value;
    }
    
    void f()
    {
        std::set s;
    
        s.insert(Element(1,2));
        s.insert(Element(2,3));
    
        std::for_each(s.begin(), s.end(), [](const Element& s) { s.incrementValue(); });
    
        std::for_each(s.begin(), s.end(), [](const Element& s) 
        { 
            std::cout << s.getValue() << std::endl; 
    
        }); 
    }
    
    int 
    main()
    {
        f();
        return 0;
    }
    

    EDIT: To be honest however you must decide if the extra level of indirection makes sense or you would be better off using a map.

提交回复
热议问题