问题
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.
回答1:
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.
回答2:
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?
回答3:
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.
回答4:
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.
回答5:
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.
来源:https://stackoverflow.com/questions/820569/is-there-a-perl-script-to-implement-c-class-get-set-member-functions