2

I have a C++ class which simulates an array and for manipulating its members I implemented two functions: set(size_t index, size_t value) and get(size_t index). I would like to overload the [] operator to have the following functionality:

MyCustomArray[index] = value //->set(size_t index, size_t value)

And

value = MyCustomArray[index] //->get(size_t index)

get can be easily implemented with overload, but I don't know how to implement set because I need the parameter value beforehand.

My class is an implementation of a fixed-word array (elements in the array have at most P bits, where P is a parameter and it can be less than the regular machine word). To support this functionality, set and get manipulate a range of bits of a value in a regular C/C++ array.

Is it possible to overload in this scenario?

Thanks in advance!

7
  • 2
    Take inspiration from std::vector<bool> and return a temporary proxy object that itself overloads operator =. Commented Jul 24, 2018 at 16:07
  • 1
    @Quentin Someone should have been generous enough to grant it its own name, instead of making it a wart on std::vector breaking generic code, but it's a good example for the needed functionality. Commented Jul 24, 2018 at 16:10
  • 1
    @PeteBecker the bit-twiddling in the last paragraph seems to prevent this simple solution. Commented Jul 24, 2018 at 16:10
  • @Deduplicator alas! But yeah, demonstration purposes only. Commented Jul 24, 2018 at 16:11
  • @Quentin -- good point. I didn't read all the way to the end. :-( Removed. Commented Jul 24, 2018 at 16:11

2 Answers 2

5

This is just like what std::vector::operator[] is doing - using a proxy object.

class MyCustomArray
{
public:
    using value_type = unsigned;
    class Proxy
    {
    public:
        friend class MyCustomArray;
        operator value_type() const 
        {
            return m_customArray.get(m_index);
        }
        Proxy & operator=(value_type value)
        {
            m_customArray.set(m_index, value);
            return *this;
        }
    private:
        Proxy(MyCustomArray & customArray, size_t index) 
            : m_customArray(customArray), m_index(index) {}
        MyCustomArray & m_customArray;
        size_t m_index;
    };
    value_type operator[](size_t index) const
    {
        return get(index);
    }
    Proxy operator[](size_t index) 
    {
        return Proxy(*this, index);
    }
    value_type get(size_t index) const;
    void set(size_t index, value_type value);
private:
    /// The data goes here
};

Then

void work(MyCustomArray & arr)
{
    // Return a Proxy object, and call operator= over it.
    arr[3] = 5;

    // arr_2 is of type MyCustomArray::Proxy
    auto arr_2 = arr[2];
    arr_2 = 1; // modifies arr[2]
    unsigned x = arr_2; // gets 1 from arr[2] 

    // This works, due to auto conversion to value_type:
    std::cout << arr_2 << '\n';
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I used this approach, and it worked perfectly!
1

As mentioned in the comments, this can be accomplished by having operator[] return a proxy object, which is how std::vector<bool> performs its magic.

In your case, it would look something along these lines:

struct MyCustomArray;

struct ArrayMemberRef {
  MyCustomArray* target_;
  std::size_t index_;

  ArrayMemberRef& operator=(std::size_t value);
  operator std::size_t();
};

struct MyCustomArray {
  ArrayMemberRef operator[](std::size_t index) {
    return ArrayMemberRef{this, index}; 
  }

  void set(std::size_t index, std::size_t value);
  int get(std::size_t index);
};

ArrayMemberRef& ArrayMemberRef::operator=(std::size_t value) {
  target_->set(index_, value);
  return *this;
}

ArrayMemberRef::operator std::size_t() {
  return target_->get(index_);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.