Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

defining operator [ ] for both reading and writing

In the book of "The C++ Programming Language", the author gave the following example along with several statements:

Defining an operator, such as [], to be used for both reading and writing is difficult where it is not acceptable simply to return a reference and let the user decide what to do with it.

Cref, is to help implement a subscript operator that distinguishes between reading and writing.

Why [] is difficult to be defined when to be used for both reading and writing? How does the definition of class Cref help to solve this issue?

  class String{
     struct Srep; 
     Srep *rep; 

     public: 
        class Cref;
        
     // some definitions here
     void check (int i) const { if (i<0 || rep->sz<=i) throw Range( );}
     
     char read( int i) const {return rep->s[i];}
     void write(int i, char c){ rep=rep->get_own_copy(); rep->s[i]=c;}

     Cref operator[] (int i){ check(i); return Cref(*this, i);}
     char operator[] (int i) const{check(i); return rep->s{i];}

   }

  class String::Cref{
    friend class String;
          String& s;
          int i;
          Cref(String& ss, int ii): s(ss),i(ii) {}
    public:
          operator char( ) { return s.read(i);}
          void operator=(char c){s.write(i,c);}
  };
like image 359
user630983 Avatar asked Mar 09 '11 03:03

user630983


People also ask

Can we overload == operator?

You should not overload operators like && and || . This is because these operators have a particular order in which an operand is evaluated. Since overloaded operators are just function calls, we cannot guarantee the order of evaluation of the operands.

Can we overload == operator in C++?

Overloading Binary Operators Suppose that we wish to overload the binary operator == to compare two Point objects. We could do it as a member function or non-member function. To overload as a member function, the declaration is as follows: class Point { public: bool operator==(const Point & rhs) const; // p1.

What is overloading operator in C++?

Operator Overloading in C++ This means C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading. For example, we can overload an operator '+' in a class like String so that we can concatenate two strings by just using +.

What is bool operator in C++?

In C++, as mentioned earlier the data type bool has been introduced to hold a boolean value, true or false. The values true or false have been added as keywords in the C++ language.


2 Answers

If you don't define a class Cref that solves this issue, then you have to do what std::map does:

template class <K,V> class map{
   V& operator[](K const & key);
}

This returns a reference, which must be backed by a valid memory location, and therefore

std::map<string,string> m;
m["foo"];
assert(m.find("foo") != m.end());

The assertion will succeed (meaning, "foo" is now a valid key in the map) even though you never assigned something to m["foo"].

This counterintuitive behavior can be fixed by the Cref class in your example -- it can perform the appropriate logic to create m["foo"] only when you assign to the reference, and ensure that m.find("foo") == m.end() if you didn't perform some assignment when you tried to read the nonexistant m["foo"].

Likewise, in your String class (which is a reference-counted string -- strings share their string data, and a new copy is created when you change a string whose data is shared with another string), you'd have to make a copy when using operator[] to read characters. The use of the Cref class, allows you to ensure that you only make a copy when using operator[] to write.

like image 177
Ken Bloom Avatar answered Sep 21 '22 05:09

Ken Bloom


String s;
s[0] = 5;

will call String::operator [](int) and then String::Cref::operator =(char).

However,

String s;
char c = s[0];

will call String::operator [](int) and then String::Cref::operator char().

When reading, String::Cref::operator char is called, and when writing String::Cref::operator = is called - this allows you to distinguish between reading and writing.

like image 45
user253751 Avatar answered Sep 21 '22 05:09

user253751