Operator Overloading C++: write-only version

有些话、适合烂在心里 提交于 2020-08-05 06:11:28

问题


I am overloading operators for a data structure, so I have the standard function declarations:

T & operator[](int i);    //used for regular objects
const T & operator[](int i) const;  // used for const objects

So what I want to do is to have a two versions of operator[] for regular objects: one that does something different when the operator[] is used to write rather than read.

I have been reading that this is possible, but I have not yet seen any code.

I have seen many times this question asked, and I have seen the answer " 'operator[] const' version is used for reading" --> but this is not true; it is used only with const instantiations of the class.

Can anyone offer guidance on detecting the write event to trigger different behavior? Is perhaps the trick in the copy constructor?


回答1:


The class holding the objects cannot get the information whether your access to the returned object is read or write access.

Only the object itself has some notion of "in which context am I used" via the member function qualifiers.

  • Ref-qualifiers
  • const/volatile qualifiers

You can use this in a proxy class.

#include <vector>
#include <type_traits>
#include <iostream>

template <class T, class U = T, bool Constant = std::is_const<T>::value>
class myproxy
{
protected:
  U& m_val;
  myproxy& operator=(myproxy const&) = delete;
public:
  myproxy(U & value) : m_val(value) { }
  operator T & ()
  {
    std::cout << "Reading." << std::endl;
    return m_val;
  }
};

template <class T>
struct myproxy < T, T, false > : public myproxy<T const, T>
{
  typedef  myproxy<T const, T> base_t;
public:
  myproxy(T & value) : base_t(value) { }
  myproxy& operator= (T const &rhs)
  {
    std::cout << "Writing." << std::endl;
    this->m_val = rhs;
    return *this;
  }
};

template<class T>
struct mycontainer
{
  std::vector<T> my_v;
  myproxy<T> operator[] (typename std::vector<T>::size_type const i)
  {
    return myproxy<T>(my_v[i]);
  }
  myproxy<T const> operator[] (typename std::vector<T>::size_type const i) const
  {
    return myproxy<T const>(my_v[i]);
  }
};

int main()
{
  mycontainer<double> test;
  mycontainer<double> const & test2(test);
  test.my_v.push_back(1.0);
  test.my_v.push_back(2.0);
  // possible, handled by "operator=" of proxy
  test[0] = 2.0;
  // possible, handled by "operator T const& ()" of proxy
  double x = test2[0];
  // Possible, handled by "operator=" of proxy
  test[0] = test2[1];
}

Prints

Writing
Reading
Reading
Writing



回答2:


As several have mentioned in the comments, you need to return a proxy, AKA smart reference, which is wrapper to the actual type T that you want, and has a link to the original object on which [] operator was called.

When the proxy is on the left side of an =, compiler will invoke its assignment operator to type T. When the proxy is on the right side of an = , compiler will invoke its cast operator to type T.

Here is a String example, I think as described in Scott Meyer's Effective C++ The first line of main should print "Writing to the String" The second line will print "Reading from the String"

struct String
{  
  char text[10];
  struct CharReference;  // forward declare char proxy class
  CharReference String::operator[] ( int index );
  void print() { printf("%s",text ); }
};




struct String::CharReference
{   CharReference( String * s, int i ) ;
     operator char ();
     const char & String::CharReference::operator = ( const char & rhs ) ;
     int index;
     String *theString;
};

const char & String::CharReference::operator = ( const char & rhs ) 
{
  printf("Writing to the string\n");
  theString->text[index] = rhs;
  return rhs;
}

String::CharReference::operator char()
{
  printf("Reading from the string\n");
  return theString->text[index];
}

String::CharReference::CharReference( String * s, int i ):theString(s), index(i) {}

 String::CharReference String::operator[] ( int index )
 {
  return CharReference( this, index); 
 }


int _tmain(int argc, _TCHAR* argv[])
{
    String s;
    s[0] = 'A';
    char c = s[0];
    return 0;
}


来源:https://stackoverflow.com/questions/26005383/operator-overloading-c-write-only-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!