const_member.cpp

(plain text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <new> // for "placement new" in class Baz

/**
 * Method 1: Make the variable name slightly uglier and tell people not to touch
 * while still allowing you to do so in operator=().
 **/
class Foo {
public:
  Foo (int size) : myConstSize(size) { }
  int size () const { return mySize(); }

private:
  int myConstSize; // don't change this!
  inline int mySize () const { return myConstSize; }
};

/**
 * Method 2: Encapsulate variable in a member object to discourage altering it
 * while still allowing you to do so in operator=().
 **/
class Bar {
public:
  Bar (int size) : mySize(size) { }
  inline int size () const { return mySize.value(); }

private:
  class size_type {
  public:
    explicit size_type (int size) : mySize(size) { }
    inline int value () const { return mySize; }

  private:
    int mySize;
  } mySize;
};

/**
 * Method 3: Destroy and rebuild the object in-place with the new value;
 * especially if the class has other member data, this is like blowing up your
 * house to kill a fly.
 **/
class Baz {
public:
  Baz (int size) : mySize(size) { }

  Baz &operator= (const Baz &rhs) {
    if (&rhs != this) {
      this->~Baz();
      new(this) Baz(rhs);
    }

    return *this;
  }

  int size () const { return mySize; } 

private:
  const int mySize;
};

/**
 * Method 4: Cast off const. Don't promise to make it const if you don't intend
 * to keep your promise. May Gord have mercy on your soul.
 **/
class Qux {
public:
  Qux (int size) : mySize(size) { }

  Qux &operator= (const Qux &rhs) {
    const_cast<int &>(mySize) = rhs.mySize;
    return *this;
  }

  int size () const { return mySize; } 

private:
  const int mySize;
};

template <typename T>
void test () {
  T x(5), y(2);
  x = y;
}

int main () {
  test<Foo>();
  test<Bar>();
  test<Baz>();
  test<Qux>();
  return 0;
}