Copy constructor / assignment operator checking

A situation I have come up a lot is that I want to write some little bit of code that executes every time a class is copy-constructed or assigned (say for reference tracking). I still want the default copy constructor / assignment operator functionality to happen-- ie, just copy over every field of the class. Since a lot of the fields are themselves objects with copy constructors / assignment operators, I can't just memcpy the whole thing.
I've tried manually writing out all of the copy instructions. The problem is, whenever anyone adds a field to the class, they need to add the appropriate line to the copy constructor and assignment operator. It's easy to forget to do that and causes horrible bugs whenever anyone forgets.
Is there any way to do any of the following:
automatically run the copy functionality without having to hand-specify all of the fields?
use some sort of macro or something like that to get a list of all fields at compile time, then right my own copy code on top of that?
check that some list of fields is in fact the complete list of fields?

I was thinking maybe I could just use sizeof and sum up all of the fields that I mention explicitly in the copy constructor, then assert that that is the size of the whole class. The only problem is that the class can be padded, so the two sums can be different even if the copy constructor is correct. Is there a way to see how much of a class's size is due to padding?
I'm not sure I understand the problem. Whenever a field is added to a class the constructor(s) should be updated also. There is no reason why that can't be done.
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
class Student
  {
  private:
    string       f_name;
    vector <int> f_test_scores;

  public:
    Student():
      f_name( "john doe" )
      {
      cout << "Default constructor: this is the constructor used if another is not specified.\n"; 
      }

    Student(
      const string&        name,
      const vector <int> & test_scores = vector <int> ()
      ):
      f_name(        name ),
      f_test_scores( test_scores )
      {
      cout << "Initializing constructor: this is used to initialize the\n"
              "object's fields at construction.\n";
      }

    Student( const Student& source ):
      f_name(        source.f_name ),
      f_test_scores( source.f_test_scores )
      {
      cout << "Copy constructor: duplicates students ;-)\n";
      }

    Student& operator = ( const Student& source )
      {
      f_name        = source.f_name;
      f_test_scores = source.f_test_scores;
      cout << "Assignment operator. Alas, only constructors take base\n"
              "initializers, so we've got to do the assignments manually.\n"; 
      }
  };


The "default copy constructor" only exists if you do not provide one. It is "default" because the compiler automatically generates a copy constructor for you if you don't. For the example above, the copy constructor is defined exactly as the compiler would have done it.

Hope this helps.

[edit] Re-reading your question, I think I understand better now. The answer is, no, not really. If you know enough macro magic you can write a macro that declares the class, but that's more trouble than just hand-initializing everything.

Sorry.
Last edited on
Topic archived. No new replies allowed.