I was reading this morning the book The Pragmatic Programmer Chapter 3 on Basic Tools every programmer should have and they mentioned Code Generation Tools.
They mentioned one Perl script for C++ programs which helped automate the process of implementing the get/set() member functions for private data members.
Does anyone know about such a script and where to find it? I've been unable to come up with the right google keywords to find it.
Although it doesn't directly answer your question, you may find that generated code is actually unnecessary for managing properties in C++. The following template code will allow you to declare and use properties conveniently:
// Declare your class containing a few properties
class my_class {
public:
property<int> x;
property<string> y;
...
};
...
my_class obj;
cout << obj.x(); // Get
obj.y("Hello, world!"); // Set
Here is the code:
// Utility template to choose the 2nd type if the 1st is void
template <typename T, typename U>
struct replace_void {
typedef T type;
};
template <typename T>
struct replace_void<void, T> {
typedef T type;
};
// Getter/setter template
template <typename T, typename D = void>
class property {
typedef typename replace_void<D, property>::type derived_type;
derived_type& derived() { return static_cast<derived_type&>(*this); }
public:
property() {} // May be safer to omit the default ctor
explicit property(T const& v) : _v(v) {}
property(property const& p) : _v(p._v) {}
property& operator=(property const& p) { _v = p._v; return *this; }
T operator()() const { return _v; } // Getter
void operator()(T const& v) { derived().check(v); _v = v; } // Setter
protected:
// Default no-op check (derive to override)
void check(T const& v) const { (void)v; //avoid unused variable warning}
private:
T _v;
};
check()
is a function that tests whether the value being assigned is valid. You can override it in a subclass:
class nonnegative_int : public property<int, nonnegative_int> {
public:
// Have to redeclare all relevant ctors unfortunately :(
nonnegative_int(int v) : property<int, nonnegative_int>(v) {}
void check(int const& v) const {
if (v < 0) {
throw "Yikes! A negative integer!";
}
}
};
There you have it -- all of the advantages of externally-generated getter/setter functions, with none of the mess! :)
You could choose to have check()
return a bool
indicating validity instead of throwing an exception. And you could in principle add a similar method, access()
, for catching read references to the property.
EDIT: As Mr. Fooz notes in the comments, the class author can later change the implementation without modifying the logical structure of the class (e.g. by replacing the property<int> x
member with a pair of x()
methods), although binary compatibility is lost so users will need to recompile their client code whenever such a change is made. This ability to painlessly incorporate future changes is actually the main reason people use getter/setter functions instead of public members in the first place.
Performance note: Because we are using the CRTP to achieve "compile-time polymorphism", there is no virtual-call overhead for providing your own check()
in a subclass, and you need not declare it virtual
.
As most C++ private members should not be accesible via Get/Set style functions, this seems like a bad idea.
For a simple example of why this is so, consider the C++ std::string class. Its private members probably look something like this (exact implementation not important):
private:
int last, len;
char * data;
Do you believe it makes any sense to provide get/set members for those?
I can't help you with the location of that particular script. However, there are quite a lot of code generation tools. You may even have what you are looking for already part of your IDE. For more debate/input on how, why, and whether to use code generation tools, you might look at this stackoverflow question. I like the accepted answer on that question.
You want a script to generate get/set functions for all of your private members indiscriminately? That wouldn't be a very useful script; you probably no going to find it in Google. If you want to be able to somehow tag your member variable and have getter and/or setter skeletons automatically generated for you, than a IDE macro seems more appropriate. Try Google for that.
I know of one programmer who uses Perl to augment the C preprocessor when it comes to macros (latest version of that project). The basic idea is you would decide on some convention to tell your Perl script when to generate a getter or setter:
struct My_struct {
//set
//get
int x;
int y;
//get
int z;
};
Given code like this, I could write a script to look for comment lines consisting of the comment "get" or "set" on the line(s) before a member variable declaration, and then replace them with simple setters/getters. In the above example I would generate void set_x(int i), int get_x(), and int get_z() after the associated member variable definitions.
A word of warning: do not do this in-place with s///. Instead, scan each line individually, and if you find an appropriate comment line push something that says "I need a getter/setter" onto a stack, then when you see the associated member variable, pop things off of the stack and generate the code.
There are a few devils in the details, but overall that is the idea.