How to detect read or write access to a user defined array?

Discussion in 'C++' started by jacob navia, Aug 26, 2007.

  1. jacob navia

    jacob navia Guest

    Hi

    Suppose that I want to create an array of read only items

    I overload the [ ] operator. How can I detect if I am being called
    within a read context
    foo = Array[23];

    or within a write context
    Array[23] = foo;

    As far as I remember, this is not possible in C++.

    Thanks
     
    jacob navia, Aug 26, 2007
    #1
    1. Advertising

  2. jacob navia

    jacob navia Guest

    Abdo Haji-Ali wrote:
    > "jacob navia" <> wrote in message
    > news:46d17343$0$27399$...
    >> Hi
    >>
    >> Suppose that I want to create an array of read only items

    > If you want a read-only array, then why don't you return a const reference?
    >
    > Abdo Haji-Ali
    > Programmer
    > In|Framez
    >
    >


    Obviously I need to initialize the array.
    I want a read only array MOST of the time.

    Context:

    We had a discussion in comp.lang.c about this, and I just want to know
    if it is possible in C++ to detect within the overloaded operator [ ]
    if we are being called for a read or for a write.

    Thanks
     
    jacob navia, Aug 26, 2007
    #2
    1. Advertising

  3. "jacob navia" <> wrote in message
    news:46d17343$0$27399$...
    > Hi
    >
    > Suppose that I want to create an array of read only items

    If you want a read-only array, then why don't you return a const reference?

    Abdo Haji-Ali
    Programmer
    In|Framez
     
    Abdo Haji-Ali, Aug 26, 2007
    #3
  4. jacob navia

    z.cHris Guest

    On Aug 26, 10:09 pm, "Abdo Haji-Ali"
    <_use_com_instead> wrote:
    > "jacob navia" <> wrote in message
    >
    > news:46d1781d$0$25947$...> We had a discussion in comp.lang.c about this, and I just want to know
    > > if it is possible in C++ to detect within the overloaded operator [ ]
    > > if we are being called for a read or for a write.

    >
    > Well then, I don't think you can. Basically a "read" operation is not always
    > a read. Consider the following:
    > int& foo = Array[0]; // Assuming that Array is an integer array
    >
    > In that case one can use 'foo' for "reading":
    > int iValue = foo;
    >
    > Or for writing:
    > foo = iValue;
    >
    > Without even refering to the original user array.
    >
    > Abdo Haji-Ali,
    > Programmer
    > In|Framez
    >
    > PS: I would make this indexer read only and provide other function for
    > "one-time" write.


    And also I could use *(Array + index) = value, to change the array
    whatever you do to [].
    So, if you want to achieve your goal, just overload the [] operator is
    not enough.

    --
    Regards
    Chris D. Cheng
     
    z.cHris, Aug 26, 2007
    #4
  5. "jacob navia" <> wrote in message
    news:46d1781d$0$25947$...
    > We had a discussion in comp.lang.c about this, and I just want to know
    > if it is possible in C++ to detect within the overloaded operator [ ]
    > if we are being called for a read or for a write.

    Well then, I don't think you can. Basically a "read" operation is not always
    a read. Consider the following:
    int& foo = Array[0]; // Assuming that Array is an integer array

    In that case one can use 'foo' for "reading":
    int iValue = foo;

    Or for writing:
    foo = iValue;

    Without even refering to the original user array.

    Abdo Haji-Ali,
    Programmer
    In|Framez

    PS: I would make this indexer read only and provide other function for
    "one-time" write.
     
    Abdo Haji-Ali, Aug 26, 2007
    #5
  6. On 2007-08-26 15:59, z.cHris wrote:
    > On Aug 26, 10:09 pm, "Abdo Haji-Ali"
    > <_use_com_instead> wrote:
    >> "jacob navia" <> wrote in message
    >>
    >> news:46d1781d$0$25947$...> We had a discussion in comp.lang.c about this, and I just want to know
    >> > if it is possible in C++ to detect within the overloaded operator [ ]
    >> > if we are being called for a read or for a write.

    >>
    >> Well then, I don't think you can. Basically a "read" operation is not always
    >> a read. Consider the following:
    >> int& foo = Array[0]; // Assuming that Array is an integer array
    >>
    >> In that case one can use 'foo' for "reading":
    >> int iValue = foo;
    >>
    >> Or for writing:
    >> foo = iValue;
    >>
    >> Without even refering to the original user array.
    >>
    >> Abdo Haji-Ali,
    >> Programmer
    >> In|Framez
    >>
    >> PS: I would make this indexer read only and provide other function for
    >> "one-time" write.

    >
    > And also I could use *(Array + index) = value, to change the array
    > whatever you do to [].
    > So, if you want to achieve your goal, just overload the [] operator is
    > not enough.


    Assuming that the items are stored in an array, that is.

    --
    Erik Wikström
     
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=, Aug 26, 2007
    #6
  7. jacob navia

    Rolf Magnus Guest

    jacob navia wrote:

    >>> Suppose that I want to create an array of read only items

    >> If you want a read-only array, then why don't you return a const
    >> reference?

    >
    > Obviously I need to initialize the array.


    Then use the object through a const reference after initializing.

    > I want a read only array MOST of the time.
    >
    > Context:
    >
    > We had a discussion in comp.lang.c about this, and I just want to know
    > if it is possible in C++ to detect within the overloaded operator [ ]
    > if we are being called for a read or for a write.


    It is not called "for a read or for a write". MyObject just calls the
    operator[] on MyObject. What you do to the object returned by that
    operator is a whole different story. So the answer to your question would
    be "no". However, you could let the operator create a proxy object that
    forwards read and write operations, which might be sufficient, depending on
    what you want.
     
    Rolf Magnus, Aug 26, 2007
    #7
  8. jacob navia

    terminator Guest

    On Aug 26, 3:33 pm, jacob navia <> wrote:
    > Hi
    >
    > Suppose that I want to create an array of read only items
    >
    > I overload the [ ] operator. How can I detect if I am being called
    > within a read context
    > foo = Array[23];
    >
    > or within a write context
    > Array[23] = foo;
    >
    > As far as I remember, this is not possible in C++.
    >
    > Thanks


    something like this will do for lots of cases:

    template <class T>
    struct contianer{
    T& operator[](unsigned);
    const T& operator[](unsigned) const;
    };

    but if you need a class for which iteration for read and write need
    different algorithms, you can easily define an indexer class:

    template <class T>
    struct contianer{
    struct indexer{
    explicit indexer(T*const,unsigned i):me(T),index(i){};
    operator T&()const;//this is the read function
    indexer& operator=(const T&)const{/*the 'write' stuff
    here*/};
    protected:
    T* const me;
    const unsigned index;
    private:
    indexer(const indexer&);
    };
    indexer operator[](unsigned i){return indexer(this,i);};
    const T& operator[](unsigned) const{return indexer(this,i).
    (operator T&)();};
    ...//class definition continues
    };

    regards,
    FM.
     
    terminator, Aug 26, 2007
    #8
  9. jacob navia

    Jerry Coffin Guest

    In article <46d17343$0$27399$>,
    says...
    > Hi
    >
    > Suppose that I want to create an array of read only items
    >
    > I overload the [ ] operator. How can I detect if I am being called
    > within a read context
    > foo = Array[23];
    >
    > or within a write context
    > Array[23] = foo;


    Make it const and have it return a reference to const. This prevents you
    from writing to the data (at all) via the operator:

    class bad_subscript {};

    template <class T>
    class const_array {
    T *data_;
    size_t size_;
    public:
    const_array(T *init, size_t size) :
    size_(size), data_(new T[size])
    {
    std::copy(init, init+size, data_);
    }

    T const &operator[](size_t subscript) const {
    if (subscript > size_)
    throw bad_subscript();
    return data_[subscript];
    }

    T *raw_data() { return data_; }
    size_t size() { return size_; }
    };

    raw_data() is a quick hack to allow writing to the data -- you haven't
    said when or how you want to allow writing to the data, so I've provided
    one way to do it. If you _only_ want to allow the data to be
    initialized, you can eliminate it (and probably add more ctors to allow
    more than one form of intialization).

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Aug 26, 2007
    #9
  10. jacob navia

    terminator Guest


    > but if you need a class for which iteration for read and write need
    > different algorithms, you can easily define an indexer class:
    >
    > template <class T>
    > struct contianer{
    > struct indexer{
    > explicit indexer(T*const,unsigned i):me(T),index(i){};

    explicit keyword is extra
    > ......
    > private:
    > indexer(const indexer&);


    oops!! delete last two lines(they were error)
    >

    regards,
    FM.
     
    terminator, Aug 26, 2007
    #10
  11. jacob navia

    terminator Guest

    On Aug 26, 3:33 pm, jacob navia <> wrote:
    > Hi
    >
    > Suppose that I want to create an array of read only items
    >

    I guess you program in C# .if you need an array of read onlies,you
    can:

    template<class T>
    struct container{
    T& operator[](unsigned);
    const T& operator[](unsigned)const;
    ....//etc
    };

    class my_class;

    container<const my_class> read_list;

    my_int=read_list[my_index];//ok
    read_list[my_index]=my_int;//error @ compile time

    container<my_class> my_list;

    const container<my_class> & my_const_list_ref=my_list;

    my_list[my_index];//call T& operator[](unsigned);
    my_const_list_ref[my_index];//call const T& operator[](unsigned)const;

    regards,
    FM.
     
    terminator, Aug 26, 2007
    #11
  12. jacob navia

    Ian Collins Guest

    jacob navia wrote:
    > Hi
    >
    > Suppose that I want to create an array of read only items
    >
    > I overload the [ ] operator. How can I detect if I am being called
    > within a read context
    > foo = Array[23];
    >
    > or within a write context
    > Array[23] = foo;
    >

    You have to use another level of indirection, something like this:

    #include <iostream>

    template <typename Taget, typename ArrayType>
    class Proxy {
    Taget& target;
    unsigned index;

    public:

    Proxy( Taget& target, unsigned index )
    : target(target), index(index) {}

    Proxy& operator=( ArrayType t ) {
    std::cout << "rhs " << index << std::endl;
    return *this;
    }

    operator ArrayType() const {
    std::cout << "lhs " << index << std::endl;
    return 42;
    }
    };

    struct Test {
    typedef Proxy<Test, int> ProxyType;

    const ProxyType operator[]( unsigned index ) const {
    return ProxyType(const_cast<Test&>(*this), index );
    }

    ProxyType operator[]( unsigned index ) {
    return ProxyType(*this, index );
    }
    };

    int main() {
    Test test;

    int n = test[0];

    test[3] = 42;
    }

    --
    Ian Collins.
     
    Ian Collins, Aug 26, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Oodini
    Replies:
    1
    Views:
    1,776
    Keith Thompson
    Sep 27, 2005
  2. Replies:
    1
    Views:
    504
    Sion Arrowsmith
    Jul 10, 2008
  3. PSN
    Replies:
    8
    Views:
    655
    Paul N
    Jun 18, 2011
  4. Randy Lawrence
    Replies:
    10
    Views:
    178
    Robert Klemme
    Jul 5, 2004
  5. sahm
    Replies:
    4
    Views:
    685
Loading...

Share This Page