As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What are your favorite C++ coding style idioms? I'm asking about style or coding typography such as where you put curly braces, are there spaces after keywords, the size of indents, etc. This is opposed to best-practices or requirements such as always deleting arrays with delete[].
Here is an example of one of my favorites: In C++ Class initializers, we put the separators at the front of the line, rather than the back. This makes it easier to keep this up to date. It also means that source code control diffs between versions are cleaner.
TextFileProcessor::
TextFileProcessor( class ConstStringFinder& theConstStringFinder )
: TextFileProcessor_Base( theConstStringFinder )
, m_ThreadHandle ( NULL )
, m_startNLSearch ( 0 )
, m_endNLSearch ( 0 )
, m_LineEndGetIdx ( 0 )
, m_LineEndPutIdx ( 0 )
, m_LineEnds ( new const void*[ sc_LineEndSize ] )
{
;
}
RAII: Resource Acquisition Is Initialization
RAII may be the most important idiom. It is the idea that resources should be mapped to objects, so that their lifetimes are managed automatically according to the scope in which those objects are declared.
For example, if a file handle was declared on the stack, it should be implicitly closed once we return from the function (or loop, or whichever scope it was declared inside). If a dynamic memory allocation was allocated as a member of a class, it should be implicitly freed when that class instance is destroyed. And so on. Every kind of resource—memory allocations, file handles, database connections, sockets, and any other kind of resource that has to be acquired and released—should be wrapped inside such a RAII class, whose lifetime is determined by the scope in which it was declared.
One major advantage of this is that C++ guarantees that destructors are called when an object goes out of scope, regardless of how control is leaving that scope. Even if an exception is thrown, all local objects will go out of scope, and so their associated resources will get cleaned up.
void foo() {
std::fstream file("bar.txt"); // open a file "bar.txt"
if (rand() % 2) {
// if this exception is thrown, we leave the function, and so
// file's destructor is called, which closes the file handle.
throw std::exception();
}
// if the exception is not called, we leave the function normally, and so
// again, file's destructor is called, which closes the file handle.
}
Regardless of how we leave the function, and of what happens after the file is opened, we don't need to explicitly close the file, or handle exceptions (e.g. try-finally) within that function. Instead, the file gets cleaned up because it is tied to a local object that gets destroyed when it goes out of scope.
RAII is also less-commonly known as SBRM (Scope-Bound Resource Management).
See also:
ScopeGuard allows code to "automatically invoke an 'undo' operation .. in the event that an exception is thrown."
When creating enumerations, put them in a namespace so that you can access them with a meaningful name:
namespace EntityType {
enum Enum {
Ground = 0,
Human,
Aerial,
Total
};
}
void foo(EntityType::Enum entityType)
{
if (entityType == EntityType::Ground) {
/*code*/
}
}
EDIT: However, this technique has become obsolete in C++11. Scoped enumeration (declared with enum class or enum struct) should be used instead: it is more type-safe, concise, and flexible. With old-style enumerations the values are placed in the outer scope. With new-style enumeration they are placed within the scope of the enum class name.
Previous example rewritten using scoped enumeration (also known as strongly typed enumeration):
enum class EntityType {
Ground = 0,
Human,
Aerial,
Total
};
void foo(EntityType entityType)
{
if (entityType == EntityType::Ground) {
/*code*/
}
}
There are other significant benefits from using scoped enumerations: absence of implicit cast, possible forward declaration, and ability to use custom underlying type (not the default int).
Copy-swap
The copy-swap idiom provides exception-safe copying. It requires that a correct copy ctor and swap are implemented.
struct String {
String(String const& other);
String& operator=(String copy) { // passed by value
copy.swap(*this); // nothrow swap
return *this; // old resources now in copy, released in its dtor
}
void swap(String& other) throw() {
using std::swap; // enable ADL, defaulting to std::swap
swap(data_members, other.data_members);
}
private:
Various data_members;
};
void swap(String& a, String& b) { // provide non-member for ADL
a.swap(b);
}
You can also implement the swap method with ADL (Argument Dependent Lookup) directly.
This idiom is important because it handles self-assignment[1], makes the strong exception guarantee[2], and is often very easy to write.
[1] Even though self-assignment isn't handled as efficiently as possible, it's supposed to be rare, so if it never happens, this is actually faster.
[2] If any exception is thrown, the state of the object (*this) is not modified.
CRTP: Curiously Recurring Template Pattern
CRTP happens when you pass a class as a template parameter to its base class:
template<class Derived>
struct BaseCRTP {};
struct Example : BaseCRTP<Example> {};
Within the base class, it can get ahold of the derived instance, complete with the derived type, simply by casting (either static_cast or dynamic_cast work):
template<class Derived>
struct BaseCRTP {
void call_foo() {
Derived& self = *static_cast<Derived*>(this);
self.foo();
}
};
struct Example : BaseCRTP<Example> {
void foo() { cout << "foo()\n"; }
};
In effect, call_foo has been injected into the derived class with full access to the derived class's members.
Feel free to edit and add specific examples of use, possibly to other SO posts.
pImpl: Pointer-to-Implementation
The pImpl idiom is a very useful way to decouple the interface of a class from its implementation.
Normally, a class definition must contain member variables as well as methods, which may expose too much information. For example, a member variable may be of a type defined in a header that we don't wish to include everywhere.
The windows.h header is a prime example here. We may wish to wrap a HANDLE or another Win32 type inside a class, but we can't put a HANDLE in the class definition without having to include windows.h everywhere the class is used.
The solution then is to create a Private IMPLementation or Pointer-to-IMPLementation of the class, and let the public implementation store only a pointer to the private one, and forward all member methods.
For example:
class private_foo; // a forward declaration a pointer may be used
// foo.h
class foo {
public:
foo();
~foo();
void bar();
private:
private_foo* pImpl;
};
// foo.cpp
#include whichever header defines the types T and U
// define the private implementation class
class private_foo {
public:
void bar() { /*...*/ }
private:
T member1;
U member2;
};
// fill in the public interface function definitions:
foo::foo() : pImpl(new private_foo()) {}
foo::~foo() { delete pImpl; }
void foo::bar() { pImpl->bar(); }
The implementation of foo is now decoupled from its public interface, so that
it can use members and types from other headers without requiring these dependencies to be present when the class is used, and
the implementation can be modified without forcing a recompile of the code that uses the class.
Users of the class simply include the header, which contains nothing specific about the implementation of the class. All implementation details are contained inside foo.cpp.
I like lining up code/initializations in 'columns'... Proves very useful when editing with a 'column' mode capable editor and also seems to be a lot easier for me to read...
int myVar = 1; // comment 1
int myLongerVar = 200; // comment 2
MyStruct arrayOfMyStruct[] =
{
// Name, timeout, valid
{"A string", 1000, true }, // Comment 1
{"Another string", 2000, false }, // Comment 2
{"Yet another string", 11111000, false }, // Comment 3
{NULL, 5, true }, // Comment 4
};
In contrast, the same code not indented and formatted as above would appear... (A little harder to read to my eyes)
int myVar = 1; // comment 1
int myLongerVar = 200; // comment 2
MyStruct arrayOfMyStruct[] =
{
// Name, timeout, valid
{"A string", 1000, true},// Comment 1
{"Another string", 2000, false }, // Comment 2
{"Yet another string", 11111000,false}, // Comment 3
{NULL, 5, true }, // Comment 4
};
Public Top - Private Down
A seemingly small optimization, but ever since I switched to this convention, I have a way more fun time to grasp my classes, especially after I haven't looked at them for 42 years.
Having a consistent member visibility, going from points of frequent interest down to the boring stuff, is extremely helpful, especially when the code ought to be self-documenting.
(sidenote for qt-users: slots come before signals because they should be callable like non-slot member functions, and apart from their slottyness be indistinguishable from non-slots)
Public, protected, private
then Factory, ctor, dtor, copying, swapping
then the class' Interface
At the very last, in a seperate private: section, comes the data (ideally only an impl-pointer).
This rule also helps a ton if you have problems keeping your class declaration uncluttered.
class Widget : public Purple {
public:
// Factory methods.
Widget FromRadians (float);
Widget FromDegrees (float);
// Ctors, rule of three, swap
Widget();
Widget (Widget const&);
Widget &operator = (Widget const &);
void swap (Widget &) throw();
// Member methods.
float area() const;
// in case of qt {{
public slots:
void invalidateBlackHole();
signals:
void areaChanged (float);
// }}
protected:
// same as public, but for protected members
private:
// same as public, but for private members
private:
// data
float widgetness_;
bool isMale_;
};
In if statements, when there are difficult conditions, you can clearly show which level each condition is using indentation.
if ( ( (var1A == var2A)
|| (var1B == var2B))
&& ( (var1C == var2C)
|| (var1D == var2D)))
{
// do something
}
re: ididak
I fix code that breaks long statements into too many short lines.
Let's face it: it's not the 90's any more.
If your company can't afford widescreen LCDs for its coders, you need to get a better job :)
Compile-time polymorphism
(Also known as syntactic polymorphism and static polymorphism, contrast with runtime polymorphism.)
With template functions, one can write code that relies on type constructors and call signatures of families of parametrized types, without having to introduce a common base class.
In the book Elements of Programming, the authors refer to this treatment of types as abstract genera. With concepts one can specify the requirements on such type parameters, though C++ doesn't mandate such specifications.
Two simple examples:
#include <stdexcept>
template <typename T>
T twice(T n) {
return 2 * n;
}
InIt find(InIt f, InIt l,
typename std::iterator_traits<InIt>::reference v)
{
while (f != l && *f != v)
++f;
return f;
}
int main(int argc, char* argv[]) {
if (6 != twice(3))
throw std::logic_error("3 x 2 = 6");
int const nums[] = { 1, 2, 3 };
if (nums + 4 != find(nums, nums + 4, 42))
throw std::logic_error("42 should not have been found.");
return 0;
}
One can call twice with any regular type that has a binary * operator defined. Similarly, one can call find() with any types that are comparable and that model Input Iterator. One set of code operates similarly on different types, with no shared base classes in sight.
Of course, what's really going on here is that it's the same source code being expanded into various type-specific functions at template instantiation time, each with separate generated machine code. Accommodating the same set of types without templates would have required either 1) separate hand-written functions with specific signatures, or 2) runtime polymorphism through virtual functions.
No favorites but I will fix code that has:
tabs - causes misalignment in many IDEs and code review tools, because they don't always agree on tab at mod 8 spaces.
lines longer than 80 columns - let's face it, shorter lines are more readable. My brain can parse most coding conventions, as long as the lines are short.
lines with trailing whitespaces - git will complain about it as whitespace errors, which show up as red blobs in diffs, which is annoying.
Here is a one-liner to find the offending files:
git grep -I -E '<tab>|.{81,}| *$' | cut -f1 -d: | sort -u
where <tab> is the tab character (POSIX regexp doesn't do \t)
if/while/for parenthesized expression(s) WITH a space separator
if (expression) // preferred - if keyword sticks out more
vs.
if(expression) // looks too much like a void function call
I guess this implies that I like my function calls to NOT have a space separator
foo(parm1, parm2);
After working with someone who was partly blind - and at his request - I switched to using many more spaces. I didn't like it at the time, but now I prefer it. Off the top of my head, the only place where there isn't whitespace between identifiers and keywords and whatnot is after a function name and before the following parentheses.
void foo( int a, int b )
{
int c = a + ( a * ( a * b ) );
if ( c > 12 )
c += 9;
return foo( 2, c );
}
Template and Hook
This is a way to handle as much as possible in a framework and give a door or hook for customization by users of a framework. Also known as Hotspot and Template Method.
class Class {
void PrintInvoice(); // Called Template (boilerplate) which uses CalcRate()
virtual void CalcRate() = 0; // Called Hook
}
class SubClass : public Class {
virtual void CalcRate(); // Customized method
}
Described by Wolfgang Pree in his book Design Patterns for Object-Oriented Software Development.
I don't know if it qualifies as an idiom, exactly, but quite a bit of heavy-duty template programming depends (often heavily) on SFINAE (substitution failure is not an error). A couple of the answers to a previous question have examples.
I really like putting a small statement on the same line as an if
int myFunc(int x) {
if(x >20) return -1;
//do other stuff ....
}
Not sure if this counts as an idiom, but I tend to use doxygen-style inline comments even when the project isn't -yet- using doxygen...
bool MyObjects::isUpToSomething() ///< Is my object up to something
(aside. my comments are not usually quite that lame.)
It's useful to put function names on a new line, so you can grep like
grep -R '^fun_name' .
for them. I've seen that style used for a loads of GNU projects and like it:
static void
fun_name (int a, int b) {
/* ... */
}
Document the return values on the function line, so they are very easy to find.
int function(void) /* return 1 on success, 0 on failure */
{
return 1;
};
Write each method or function argument on a separate line such that it can be easily commented.
int ReturnMaxValue(
int* inputList, /* the list of integer values from which to get the maximum */
long size, /* count of the number of integer values in inputList */
char* extraArgs /* additional arguments that a caller can provide. */
)
I'd suggest PIMPL or as James Coplien originally called it "Handle Body".
This idiom allows you to completely decouple interface from implementation. When working on the rewrite and re-release of a major CORBA middleware component, this idiom was used to completely decouple the API from the implementation.
This practically eliminated any possibility reverse engineering.
An excellent resource for C++ idioms is James Coplien's excellent book "Advanced C++ Programming Styles and Idioms". Highly recommended!
Edit: As pointed out below by Neil, this book is quite out of date with many of his recommendations actually being incorporated into the C++ standard itself. However, I still find it to be a source of useful info, esp. in the form of his PLoP paper on C++ idioms where many idioms were recast into patterm form.
I always nitpick and edit the following:
Superfluous newlines
No newline at EOF
I usually stick to KNF described in *BSD STYLE(9)
I tend to put an else on all of my ifs.
if (condition)
{
complicated code goes here
}
else
{
/* This is a comment as to why the else path isn't significant */
}
Even though it annoys my coworkers.
You can tell at a glance, that I considered the else case during coding.
Related
I am writing a program that has the option to visualize the output of an algorithm I am working on - this is done by changing a const bool VISUALIZE_OUTPUT variable defined in a header file. In the main file, I want to have this kind of pattern:
if(VISUALIZE_OUTPUT) {
VisualizerObject vis_object;
}
...
if(VISUALIZE_OUTPUT) {
vis_object.initscene(objects_here);
}
...
if(VISUALIZE_OUTPUT) {
vis_object.drawScene(objects_here);
}
However, this clearly won't compile since vis_object goes out of scope. I don't want to declare the object before the condition since it is a big object and it needs to available for multiple points in the code (I can't just have one conditional statement where everything is done).
What is the preferred way of doing this?
Declare the object on the heap and refer to it by using a pointer (or
unique_ptr)?
Declare the object on the heap and make a reference to it
since it won't ever change?
Some other alternative?
A reference will not be useable here, because at declaration it should refere to an already existing object, and live in a scope englobing all your if(VISUALIZE_OUTPUT). Long story short, the object will have to be created unconditionally.
So IMHO a simple way would be to create it on the heap and use it through a pointer - do not forget do delete it when done. The good point is that the pointer could be initialized to nullptr, and so it could be unconditionnaly deleted.
But I think that the best way would be to encapsulate everything in an object created in highest scope. This object would then contain methods to create, use internally and finally destroy the actual vis_object. That way, if you do not need it, nothing will be actually instanciated, but the main procedure will not be cluttered with raw pointer processing.
I would use Null_object_pattern:
struct IVisualizerObject
{
virtual ~IVisualizerObject() = default;
virtual void initscene(Object&) = 0;
virtual void drawScene(Object&) = 0;
// ...
};
struct NullVisualizerObject : IVisualizerObject
{
void initscene(Object&) override { /* Empty */ }
void drawScene(Object&) override { /* Empty */}
// ...
};
struct VisualizerObject : IVisualizerObject
{
void initscene(Object& o) override { /*Implementation*/}
void drawScene(Object& o) override { /*Implementation*/}
// ...
};
And finally:
std::unique_ptr<IVisualizerObject> vis_object;
if (VISUALIZE_OUTPUT) {
vis_object = std::make_unique<VisualizerObject>();
} else {
vis_object = std::make_unique<NullVisualizer>();
}
// ...
vis_object->initscene(objects_here);
//...
vis_object->drawScene(objects_here);
I'll give a few options. All have upsides and downsides.
If it is NOT possible to modify VisualizerObject, as I noted in comments, the effect could be achieved by using the preprocessor, since the preprocessor does not respect scope, and the question specifically seeks controlling lifetime of an object in a manner that crosses scope boundaries.
#ifdef VISUALIZE_OUTPUT
VisualizerObject vis_object;
#endif
#ifdef VISUALIZE_OUTPUT
vis_object.initscene(objects_here);
#endif
The compiler will diagnose any usage of vis_object that are not in #ifdef/#endif.
The big criticism, of course, is that use of the preprocessor is considered poor practice in C++. The advantage is that the approach can be used even if it is not possible to modify the VisualizerObject class (e.g. because it is in a third-party library without source code provided).
However, this is the only option that has the feature requested by the OP of object lifetime crossing scope boundaries.
If it is possible to modify the VisualizerObject class, make it a template with two specialisations
template<bool visualise> struct VisualizerObject
{
// implement all member functions required to do nothing and have no members
VisualizerObject() {};
void initscene(types_here) {};
};
template<> struct VisualizerObject<true> // heavyweight implementation with lots of members
{
VisualizerObject(): heavy1(), heavy2() {};
void initscene(types_here) { expensive_operations_here();};
HeavyWeight1 heavy1;
HeavyWeight2 heavy2;
};
int main()
{
VisualizerObject<VISUALIZE_OUTPUT> vis_object;
...
vis_object.initscene(objects_here);
...
vis_object.drawScene(objects_here);
}
The above will work in all C++ versions. Essentially, it works by either instantiating a lightweight object with member functions that do nothing, or instantiating the heavyweight version.
It would also be possible to use the above approach to wrap a VisualizerObject.
template<bool visualise> VisualizerWrapper
{
// implement all required member functions to do nothing
// don't supply any members either
}
template<> VisualizerWrapper<true>
{
VisualizerWrapper() : object() {};
// implement all member functions as forwarders
void initscene(types_here) { object.initscene(types_here);};
VisualizerObject object;
}
int main()
{
VisualizerWrapper<VISUALIZE_OUTPUT> vis_object;
...
vis_object.initscene(objects_here);
...
vis_object.drawScene(objects_here);
}
The disadvantage of both of the template approaches is maintenance - when adding a member function to one class (template specialisation) it is necessary to add a function with the same signature to the other. In large team settings, it is likely that testing/building will be mostly done with one setting of VISUALIZE_OUTPUT or the other - so it is easy to get one version out of alignment (different interface) to the other. Problems of that (e.g. a failed build on changing the setting) are likely to emerge at inconvenient times - such as when there is a tight deadline to deliver a different version of the product.
Pedantically, the other downside of the template options is that they don't comply with the desired "kind of pattern" i.e. the if is not required in
if(VISUALIZE_OUTPUT)
{
vis_object.initscene(objects_here);
}
and object lifetimes do not cross scope boundaries.
in Java code convention is simple and obvious, in this style:
public:
int GetMyAge(){
return myAge;
}
void SetMyAge(int myAge){
this->myAge = myAge;
}
private:
int myAge;
(I know it's "again the same thing", but) I have read most of related questions on SO and I still don't know "the best one" and "the most official" way to do it in C++. It can't be just a matter of preferences, can it?
EDIT:
Seems like it can.
Best not to do it at all. Can your age actually be changed like that? Blindly providing getters and setters for all properties is a sign you have not designed your class properly.
The best style is the one that allows you and your team to make quality software that your clients continue to pay you for.
How does this style work for you and your team? Do you find it causes (or prevents) bugs? Do you find it easy to maintain the code? Do you bicker about the formatting?
Answer those questions and the answer to your question will arise out of them.
A simple answer: class names are capital in general in c++ (except for the std classes), methods are lower case, some frameworks like Qt prefer camelCase, however I prefer underscore_notation -- and so do the STL see eg. "auto_ptr".
Classes do not always have separate .h files, because here a .java file is split up into a .h header (for an entire package), and .cpp implementation files, one per class.
class TipicalCamelCase {
public:
/// mark the frequently used small functions inline in the class def.
inline int getMyAge() const;
void setMyAge(int myAge=5); // defaults go to the definition.
/// for efficiently setting more complex things.
void setMyStuff(const MyStuff& myStuff);
/// a tipical class-valued getter
/// (sometimes scoffed at since it can have memory leaks
/// if you dismiss the class but still use and don't copy MyStuff.)
const MyStuff& getMyStuff() const;
/// a safe getter, but forces copying-out MyStuff.
MyStuff getMyStuff() const;
private:
int myAge;
static const int zero=0; // allowed only in the new C++11 standard.
static const int one;
};
Some implementations/initializations (usually in separate TipicalCamelCase.cpp file):
const int TipicalCamelCase::one = 1;
int TipicalCamelCase::getMyAge() const{
return myAge;
}
void TipicalCamelCase::setMyAge(int myAge_){
myAge = myAge_;
}
Underscore style is the same but
int Tipical_camel_case::get_my_age() const
{
return my_age;
}
I prefer this as it looks cleaner both in the header and in the implementation files.
You can see that function headlines are lengthier than in java. Especially you'll see with templates (generics) 2 lines' header is typical, so it is worth to put them a bit more separated.
template<typename _Tp>
int Class_name::general_function(_Tp);
I think it should do as a style intro.
If you use inheritance, for the java-style working, mark every function except the constructors virtual so that the #overrides behave correctly.
What you have written in the above code is a correct syntax . If you are looking for a thumb rule, code your acccessor functions in such a way that they are set / get exactly the values .
EG :
void SetMyAge(int newAge)
{
if(newAge > 10 && newAge < 100)
_age = newAge ;
}
I would prefer to put the validation "newAge > 10 && newAge < 100" in a different function, IsValidAge ; even if the code is just one line. On the long run, small functions help in maintaining the code, and helps new developers to understand the code better.
void SetMyAge(int newAge)
{
if(IsValidAge() )
_age = newAge ;
}
However I would like to comment on this
void SetMyAge(int myAge){
this->myAge = myAge;
}
It is good practice to differentiate the nameing convention of the class varaiable to _myAge .
EDIT
I think the variable name was comprehended improperly .
myAge should be named _myAge .
I have a set of classes that describe a set of logical boxes that can hold things and do things to them. I have
struct IBox // all boxes do these
{
....
}
struct IBoxCanDoX // the power to do X
{
void x();
}
struct IBoxCanDoY // the power to do Y
{
void y();
}
I wonder what is the 'best' or maybe its just 'favorite' idiom for a client of these classes to deal with these optional capabilities
a)
if(typeid(box) == typeid(IBoxCanDoX))
{
IBoxCanDoX *ix = static_cast<IBoxCanDoX*>(box);
ix->x();
}
b)
IBoxCanDoX *ix = dynamic_cast<IBoxCanDoX*>(box);
if(ix)
{
ix->x();
}
c)
if(box->canDoX())
{
IBoxCanDoX *ix = static_cast<IBoxCanDoX*>(box);
ix->x();
}
d) different class struct now
struct IBox
{
void x();
void y();
}
...
box->x(); /// ignored by implementations that dont do x
e) same except
box->x() // 'not implemented' exception thrown
f) explicit test function
if(box->canDoX())
{
box->x();
}
I am sure there are others too.
EDIT:
Just to make the use case clearer
I am exposing this stuff to end users via interactive ui. They can type 'make box do X'. I need to know if box can do x. Or I need to disable the 'make current box do X' command
EDIT2: Thx to all answerers
as Noah Roberts pointed out (a) doesnt work (explains some of my issues !).
I ended up doing (b) and a slight variant
template<class T>
T* GetCurrentBox()
{
if (!current_box)
throw "current box not set";
T* ret = dynamic_cast<T*>(current_box);
if(!ret)
throw "current box doesnt support requested operation";
return ret;
}
...
IBoxCanDoX *ix = GetCurrentBox<IBoxCanDoX>();
ix->x();
and let the UI plumbing deal nicely with the exceptions (I am not really throwing naked strings).
I also intend to explore Visitor
I suggest the Visitor pattern for double-dispatch problems like this in C++:
class IVisitor
{
public:
virtual void Visit(IBoxCanDoX *pBox) = 0;
virtual void Visit(IBoxCanDoY *pBox) = 0;
virtual void Visit(IBox* pBox) = 0;
};
class IBox // all boxes do these
{
public:
virtual void Accept(IVisitor *pVisitor)
{
pVisitor->Visit(this);
}
};
class BoxCanDoY : public IBox
{
public:
virtual void Accept(IVisitor *pVisitor)
{
pVisitor->Visit(this);
}
};
class TestVisitor : public IVisitor
{
public:
// override visit methods to do tests for each type.
};
void Main()
{
BoxCanDoY y;
TestVisitor v;
y.Accept(&v);
}
Of the options you've given, I'd say that b or d are "best". However, the need to do a lot of this sort of thing is often indicative of a poor design, or of a design that would be better implemented in a dynamically typed language rather than in C++.
If you are using the 'I' prefix to mean "interface" as it would mean in Java, which would be done with abstract bases in C++, then your first option will fail to work....so that one's out. I have used it for some things though.
Don't do 'd', it will pollute your hierarchy. Keep your interfaces clean, you'll be glad you did. Thus a Vehicle class doesn't have a pedal() function because only some vehicles can pedal. If a client needs the pedal() function then it really does need to know about those classes that can.
Stay way clear of 'e' for the same reason as 'd' PLUS that it violates the Liskov Substitution Principle. If a client needs to check that a class responds to pedal() before calling it so that it doesn't explode then the best way to do that is to attempt casting to an object that has that function. 'f' is just the same thing with the check.
'c' is superfluous. If you have your hierarchy set up the way it should be then casting to ICanDoX is sufficient to check if x can do X().
Thus 'b' becomes your answer from the options given. However, as Gladfelter demonstrates, there are options you haven't considered in your post.
Edit note: I did not notice that 'c' used a static_cast rather than dynamic. As I mention in an answer about that, the dynamic_cast version is cleaner and should be preferred unless specific situations dictate otherwise. It's similar to the following options in that it pollutes the base interface.
Edit 2: I should note that in regard to 'a', I have used it but I don't use types statically like you have in your post. Any time I've used typeid to split flow based on type it has always been based on something that is registered during runtime. For example, opening the correct dialog to edit some object of unknown type: the dialog governors are registered with a factory based on the type they edit. This keeps me from having to change any of the flow control code when I add/remove/change objects. I generally wouldn't use this option under different circumstances.
A and B require run time type identification(RTTI) and might be slower if you are doing a lot checks. Personally I don't like the solutions of "canDoX" methods, if situations like this arise the design probably needs an upgrade because you are exposing information that is not relevant to the class.
If you only need to execute X or Y, depending on the class, I would go for a virtual method in IBox which get overridden in subclasses.
class IBox{
virtual void doThing();
}
class IBoxCanDoX: public IBox{
void doThing() { doX(); }
void doX();
}
class IBoxCanDoY: public IBox{
void doThing() { doY(); }
void doY();
}
box->doThing();
If that solution is not applicable or you need more complex logic, then look at the Visitor design pattern. But keep in mind that the visitor pattern is not very flexible when you add new classes regularly or methods change/are added/are removed (but that also goes true for your proposed alternatives).
If you are trying to call either of these classes actions from contingent parts of code, you I would suggest you wrap that code in a template function and name each class's methods the same way to implement duck typing, thus your client code would look like this.
template<class box>
void box_do_xory(box BOX){
BOX.xory();
}
There is no general answer to your question. Everything depends. I can say only that:
- don't use a), use b) instead
- b) is nice, requires least code, no need for dummy methods, but dynamic_cast is a little slow
- c) is similar to b) but it is faster (no dynamic_cast) and requires more memory
- e) has no sense, you still need to discover if you can call the method so the exception is not thrown
- d) is better then f) (less code to write)
- d) e) and f) produce more garbage code then others, but are faster and less memory consuming
I assume that you will not only be working with one object of one type here.
I would lay out the data that you are working with and try to see how you can lay it out in memory in order to do data-driven programming. A good layout in memory should reflect the way that you store the data in your classes and how the classes are layed out in memory. Once you have that basic design structured (shouldn't take more than a napkin), I would begin organizing the objects into lists dependent on the operations that you plan to do on the data. If you plan to do X() on a collection of objects { Y } in the subset X, I would probably make sure to have a static array of Y that I create from the beginning. If you wish to access the entire of X occasionally, that can be arranged by collecting the lists into a dynamic list of pointers (using std::vector or your favorite choice).
I hope that makes sense, but once implemented it gives simple straight solutions that are easy to understand and easy to work with.
There is a generic way to test if a class supports a certain concept and then to execute the most appropriate code. It uses SFINAE hack. This example is inspired by Abrahams and Gurtovoy's "C++ Template Metaprogramming" book. The function doIt will use x method if it is present, otherwise it will use y method. You can extend CanDo structure to test for other methods as well. You can test as many methods as you wish, as long as the overloads of doIt can be resolved uniquely.
#include <iostream>
#include <boost/config.hpp>
#include <boost/utility/enable_if.hpp>
typedef char yes; // sizeof(yes) == 1
typedef char (&no)[2]; // sizeof(no) == 2
template<typename T>
struct CanDo {
template<typename U, void (U::*)()>
struct ptr_to_mem {};
template<typename U>
static yes testX(ptr_to_mem<U, &U::x>*);
template<typename U>
static no testX(...);
BOOST_STATIC_CONSTANT(bool, value = sizeof(testX<T>(0)) == sizeof(yes));
};
struct DoX {
void x() { std::cout << "doing x...\n"; }
};
struct DoAnotherX {
void x() { std::cout << "doing another x...\n"; }
};
struct DoY {
void y() { std::cout << "doing y...\n"; }
};
struct DoAnotherY {
void y() { std::cout << "doing another y...\n"; }
};
template <typename Action>
typename boost::enable_if<CanDo<Action> >::type
doIt(Action* a) {
a->x();
}
template <typename Action>
typename boost::disable_if<CanDo<Action> >::type
doIt(Action* a) {
a->y();
}
int main() {
DoX doX;
DoAnotherX doAnotherX;
DoY doY;
DoAnotherY doAnotherY;
doIt(&doX);
doIt(&doAnotherX);
doIt(&doY);
doIt(&doAnotherY);
}
The problem:
I have a C++ class with gajillion (>100) members that behave nearly identically:
same type
in a function, each member has the same exact code done to it as other members, e.g. assignment from a map in a constructor where map key is same as member key
This identicality of behavior is repeated across many-many functions (>20), of course the behavior in each function is different so there's no way to factor things out.
The list of members is very fluid, with constant additions and sometimes deletions, some (but not all) driven by changing columns in a DB table.
As you can imagine, this presents a big pain-in-the-behind as far as code creation and maintenance, since to add a new member you have to add code to every function
where analogous members are used.
Example of a solution I'd like
Actual C++ code I need (say, in constructor):
MyClass::MyClass(SomeMap & map) { // construct an object from a map
intMember1 = map["intMember1"];
intMember2 = map["intMember2"];
... // Up to
intMemberN = map["intMemberN"];
}
C++ code I want to be able to write:
MyClass::MyClass(SomeMap & map) { // construct an object from a map
#FOR_EACH_WORD Label ("intMember1", "intMember2", ... "intMemberN")
$Label = map["$Label"];
#END_FOR_EACH_WORD
}
Requirements
The solution must be compatible with GCC (with Nmake as make system, if that matters).
Don't care about other compilers.
The solution can be on a pre-processor level, or something compilable. I'm fine with either one; but so far, all of my research pointed me to the conclusion that the latter is just plain out impossible in C++ (I so miss Perl now that I'm forced to do C++ !)
The solution must be to at least some extent "industry standard" (e.g. Boost is great, but a custom Perl script that Joe-Quick-Fingers created once and posted on his blog is not. Heck, I can easily write that Perl script, being much more of a Perl expert than a C++ one - I just can't get bigwigs in Software Engineering at my BigCompany to buy into using it :) )
The solution should allow me to declare a list of IDs (ideally, in only one header file instead of in every "#FOR_EACH_WORD" directive as I did in the example above)
The solution must not be limited to "create an object from a DB table" constructor. There are many functions, most of them not constructors, that need this.
A solution of "Make them all values in a single vector, and then run a 'for' loop across the vector" is an obvious one, and can not be used - the code's in a library used by many apps, the members are public, and re-writing those apps to use vector members instead of named members is out of the question, sadly.
Boost includes a great preprocessor library that you can use to generate such code:
#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/cat.hpp>
typedef std::map<std::string, int> SomeMap;
class MyClass
{
public:
int intMember1, intMember2, intMember3;
MyClass(SomeMap & map)
{
#define ASSIGN(z,n,_) BOOST_PP_CAT(intMember, n) = map[ BOOST_PP_STRINGIZE(BOOST_PP_CAT(intMember, n))];
BOOST_PP_REPEAT_FROM_TO(1, 4, ASSIGN, nil)
}
};
Boost.Preprocessor proposes many convenient macros to perform such operations. Bojan Resnik already provided a solution using this library, but it assumes that every member name is constructed the same way.
Since you explicitely required the possibily to declare a list of IDs, here is a solution that should better fulfill your needs.
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
// sequence of member names (can be declared in a separate header file)
#define MEMBERS (foo)(bar)
// macro for the map example
#define GET_FROM_MAP(r, map, member) member = map[BOOST_PP_STRINGIZE(member)];
BOOST_PP_SEQ_FOR_EACH(GET_FROM_MAP, mymap, MEMBERS)
// generates
// foo = mymap["foo"]; bar = mymap["bar];
-------
//Somewhere else, we need to print all the values on the standard output:
#define PRINT(r, ostream, member) ostream << member << std::endl;
BOOST_PP_SEQ_FOR_EACH(PRINT, std::cout, MEMBERS)
As you can see, you just need to write a macro representing the pattern you want to repeat, and pass it to the BOOST_PP_SEQ_FOR_EACH macro.
You could do something like this: create an adapter class or modify the existing class to have a vector of pointers to those fields, add the addresses of all member variables in question to that vector in the class constructor, then when needed run the for-loop on that vector. This way you don't (or almost don't) change the class for external users and have a nice for-loop capability.
Of course, the obvious question is: Why do you have a class with 100 members? It doesn't really seem sane.
Assuming it is sane nevertheless -- have you looked at boost preprocessor library? I have never used it myself (as one friend used to say: doing so leads to the dark side), but from what I heard it should be the tool for the job.
Surreptitiously use perl on your own machine to create the constructor. Then ask to increase your salary since you're succesfully maintaining such a huge chunk of code.
You could use the preprocessor to define the members, and later use the same definition to access them:
#define MEMBERS\
MEMBER( int, value )\
SEP MEMBER( double, value2 )\
SEP MEMBER( std::string, value3 )\
struct FluctuatingMembers {
#define SEP ;
#define MEMBER( type, name ) type name
MEMBERS
#undef MEMBER
#undef SEP
};
.. client code:
FluctuatingMembers f = { 1,2., "valuesofstringtype" };
std::cout <<
#define SEP <<
#define MEMBER( type, name ) #name << ":" << f.##name
MEMBERS;
#undef MEMBER
#undef SEP
It worked for me, but is hard to debug.
You can also implement a visitor pattern based on pointer-to-members. After the preprocessor solution, this one turns out way more debuggeable.
struct FluctuatingMembers {
int v1;
double v2;
std::string v3;
template<typename Visitor> static void each_member( Visitor& v );
};
template<typename Visitor> void FluctuatingMembers::each_member( Visitor& v ) {
v.accept( &FluctuatingMembers::v1 );
v.accept( &FluctuatingMembers::v2 );
v.accept( &FluctuatingMembers::v3 );
}
struct Printer {
FluctuatingMembers& f;
template< typename pt_member > void accept( pt_member m ) const {
std::cout << (f::*m) << "\n";
}
};
// you can even use this approach for visiting
// multiple objects simultaneously
struct MemberComparer {
FluctuatingMembers& f1, &f2;
bool different;
MemberComparer( FluctuatingMembers& f1, FluctuatingMembers& f2 )
: f1(f1),f2(f2)
,different(false)
{}
template< typename pt_member > void accept( pt_member m ) {
if( (f1::*m) != (f2::*m) ) different = true;
}
};
... client code:
FluctuatingMembers object1 = { 1, 2.2, "value2" }
, object2 = { 1, 2.2, "valuetoo" };
Comparer compare( object1, object2 );
FluctuatingMembers::each_member( compare );
Printer pr = { object1 };
FluctuatingMembers::each_member( pr );
Why not do it at run time? (I really hate macro hackery)
What you really are asking for, in some sense, is class metadata.
So I would try something like:
class AMember{
......
};
class YourClass{
AMember member1;
AMember member2;
....
AMember memberN;
typedef AMember YourClass::* pMember_t;
struct MetaData : public std::vector<std::pair<std::string,pMember_t>>{
MetaData(){
push_back(std::make_pair(std::string("member1"),&YourClass::member1));
...
push_back(std::make_pair(std::string("memberN"),&YourClass::memberN));
}
};
static const MetaData& myMetaData() {
static const MetaData m;//initialized once
return m;
}
YourClass(const std::map<std::string,AMember>& m){
const MetaData& md = myMetaData();
for(MetaData::const_iterator i = md.begin();i!= md.end();++i){
this->*(i->second) = m[i->first];
}
}
YourClass(const std::vector<std::pair<std::string,pMember_t>>& m){
const MetaData& md = myMetaData();
for(MetaData::const_iterator i = md.begin();i!= md.end();++i){
this->*(i->second) = m[i->first];
}
}
};
(pretty sure I've got the syntax right but this is a machinery post not a code post)
RE:
in a function, each member has the same exact code done to it as other members, e.g. assignment from a map in a constructor where map key is same as member key
this is handled above.
RE:
The list of members is very fluid, with constant additions and sometimes deletions, some (but not all) driven by changing columns in a DB table.
When you add a new AMember, say newMember, all you have to do is update the MetaData constructor with an:
push_back(make_pair(std::string("newMember"),&YourClass::newMember));
RE:
This identicality of behavior is repeated across many-many functions (>20), of course the behavior in each function is different so there's no way to factor things out.
You have the machinery to apply this same idiom to build the functions
eg: setAllValuesTo(const AMember& value)
YourClass::setAllValuesTo(const AMember& value){
const MetaData& md = myMetaData();
for(MetaData::const_iterator i = md.begin();i!= md.end();++i){
this->*(i->second) = value;
}
}
If you are a tiny bit creative with function pointers or template functionals you can factor out the mutating operation and do just about anything you want to YourClass' AMember's on a collection basis. Wrap these general functions (that may take a functional or function pointer) to implement your current set of 20 public methods in the interface.
If you need more metadata just augment the codomain of the MetaData map beyond a pointer to member. (Of course the i->second above would change then)
Hope this helps.
You can do something like his:
#define DOTHAT(m) m = map[#m]
DOTHAT(member1); DOTHAT(member2);
#undef DOTHAT
That doesn't fully fit your description, but closest to it that saves you typing.
Probably what I'd look to do would be to make use of runtime polymorphism (dynamic dispatch). Make a parent class for those members with a method that does the common stuff. The members derive their class from that parent class. The ones that need a different implementation of the method implement their own. If they need the common stuff done too, then inside the method they can downcast to the base class and call its version of the method.
Then all you have to do inside your original class is call the member for each method.
I would recommend a small command-line app, written in whatever language you or your team are most proficient in.
Add some kind of template language to your source files. For something like this, you don't need to implement a full-fledged parser or anything fancy like that. Just look for an easily-identified character at the beginning of a line, and some keywords to replace.
Use the command-line app to convert the templated source files into real source files. In most build systems, this should be pretty easy to do automatically by adding a build phase, or simply telling the build system: "use MyParser.exe to handle files of type *.tmp"
Here's an example of what I'm talking about:
MyClass.tmp
MyClass::MyClass(SomeMap & map) { // construct an object from a map
▐REPLACE_EACH, LABEL, "intMember1", "intMember2, ... , "intMemberN"
▐ LABEL = map["$Label"];
}
I've used "▐" as an example, but any character that would otherwise never appear as the first character on a line is perfectly acceptable.
Now, you would treat these .tmp files as your source files, and have the actual C++ code generated automatically.
If you've ever heard the phrase "write code that writes code", this is what it means :)
There are already a lot of good answers and ideas here, but for the sake of diversity I'll present another.
In the code file for MyClass would be:
struct MemberData
{
size_t Offset;
const char* ID;
};
static const MemberData MyClassMembers[] =
{
{ offsetof(MyClass, Member1), "Member1" },
{ offsetof(MyClass, Member2), "Member2" },
{ offsetof(MyClass, Member3), "Member3" },
};
size_t GetMemberCount(void)
{
return sizeof(MyClassMembers)/sizeof(MyClassMembers[0]);
}
const char* GetMemberID(size_t i)
{
return MyClassMembers[i].ID;
}
int* GetMemberPtr(MyClass* p, size_t i) const
{
return (int*)(((char*)p) + MyClassMembers[i].Offset);
}
Which then makes it possible to write the desired constructor as:
MyClass::MyClass(SomeMap& Map)
{
for(size_t i=0; i<GetMemberCount(); ++i)
{
*GetMemberPtr(i) = Map[GetMemberID(i)];
}
}
And of course, for any other functions operating on all the members you would write similar loops.
Now there are a few issues with this technique:
Operations on members use a runtime loop as opposed to other solutions which would yield an unrolled sequence of operations.
This absolutely depends on each member having the same type. While that was allowed by OP, one should still evaluate whether or not that might change in the future. Some of the other solutions don't have this restriction.
If I remember correctly, offsetof is only defined to work on POD types by the C++ standard. In practice, I've never seen it fail. However I haven't used all the C++ compilers out there. In particular, I've never used GCC. So you would need to test this in your environment to ensure it actually works as intended.
Whether or not any of these are problems is something you'll have to evaluate against your own situation.
Now, assuming this technique is usable, there is one nice advantage. Those GetMemberX functions can be turned into public static/member functions of your class, thus providing this generic member access to more places in your code.
class MyClass
{
public:
MyClass(SomeMap& Map);
int Member1;
int Member2;
int Member3;
static size_t GetMemberCount(void);
static const char* GetMemberID(size_t i);
int* GetMemberPtr(size_t i) const;
};
And if useful, you could also add a GetMemberPtrByID function to search for a given string ID and return a pointer to the corresponding member.
One disadvantage with this idea so far is that there is a risk that a member could be added to the class but not to the MyClassMembers array. However, this technique could be combined with xtofl's macro solution so that a single list could populate both the class and the array.
changes in the header:
#define MEMBERS\
MEMBER( Member1 )\
SEP MEMBER( Member2 )\
SEP MEMBER( Member3 )\
class MyClass
{
public:
#define SEP ;
#define MEMBER( name ) int name
MEMBERS;
#undef MEMBER
#undef SEP
// other stuff, member functions, etc
};
and changes in the code file:
const MemberData MyClassMembers[] =
{
#define SEP ,
#define MEMBER( name ) { offsetof(MyClass, name), #name }
MEMBERS
#undef MEMBER
#undef SEP
};
Note: I have left error checking out of my examples here. Depending on how this would be used, you might want to ensure the array bounds are not overrun with debug mode asserts and/or release mode checks that would return NULL pointers for bad indexes. Or some use of exceptions if appropriate.
Of course, if you aren't worried about error checking the array bounds, then GetMemberPtr could actually be changed into something else that would return a reference to the member.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am familiar with C++ RTTI, and find the concept interesting.
Still there exist a lot of more ways to abuse it than to use it correctly (the RTTI-switch dread comes to mind). As a developer, I found (and used) only two viable uses for it (more exactly, one and a half).
Could you share some of the ways RTTI is a viable solution to a problem, with example code/pseudo-code included?
Note: The aim is to have a repository of viable examples a junior developer can consult, criticize and learn from.
Edit: You'll find below code using C++ RTTI
// A has a virtual destructor (i.e. is polymorphic)
// B has a virtual destructor (i.e. is polymorphic)
// B does (or does not ... pick your poison) inherits from A
void doSomething(A * a)
{
// typeid()::name() returns the "name" of the object (not portable)
std::cout << "a is [" << typeid(*a).name() << "]"<< std::endl ;
// the dynamic_cast of a pointer to another will return NULL is
// the conversion is not possible
if(B * b = dynamic_cast<B *>(a))
{
std::cout << "a is b" << std::endl ;
}
else
{
std::cout << "a is NOT b" << std::endl ;
}
}
Acyclic Visitor (pdf) is a great use of it.
How about the boost::any object!
This basically uses the RTTI info to store any object and the retrieve that object use boost::any_cast<>.
You can use RTTI with dynamic_cast to get a pointer to a derived class in order to use it to call a fast, type specialized algorithm. And instead of using the virtual methods through the base class, it will make direct and inlined calls.
This sped things up for me a lot using GCC. Visual Studio didn't seem to do as well, it may have a slower dynamic_cast lookup.
Example:
D* obj = dynamic_cast<D*>(base);
if (obj) {
for(unsigned i=0; i<1000; ++i)
f(obj->D::key(i));
}
} else {
for(unsigned i=0; i<1000; ++i)
f(base->key(i));
}
}
I cant say I've ever found a use for in in real life but RTTI is mentioned in Effective C++ as a possible solution to multi-methods in C++. This is because method dispatch is done on the dynamic type of the this parameter but the static type of the arguments.
class base
{
void foo(base *b) = 0; // dynamic on the parameter type as well
};
class B : public base {...}
class B1 : public B {...}
class B2 : public B {...}
class A : public base
{
void foo(base *b)
{
if (B1 *b1=dynamic_cast<B1*>(b))
doFoo(b1);
else if (B2 *b2=dynamic_cast<B2*>(b))
doFoo(b2);
}
};
I worked on an aircraft simulation once, that had what they (somewhat confusingly) referred to as a "Simulation Database". You could register variables like floats or ints or strings in it, and people could search for them by name, and pull out a reference to them. You could also register a model (an object of a class descended from "SimModel"). The way I used RTTI, was to make it so you could search for models that implement a given interface:
SimModel* SimDatabase::FindModel<type*>(char* name="")
{
foreach(SimModel* mo in ModelList)
if(name == "" || mo->name eq name)
{
if(dynamic_cast<type*>mo != NULL)
{
return dynamic_cast<type*>mo;
}
}
return NULL;
}
The SimModel base class:
class public SimModel
{
public:
void RunModel()=0;
};
An example interface might be "EngineModel":
class EngineModelInterface : public SimModel
{
public:
float RPM()=0;
float FuelFlow()=0;
void SetThrottle(float setting)=0;
};
Now, to make a Lycoming and Continental engine:
class LycomingIO540 : public EngineModelInterface
{
public:
float RPM()
{
return rpm;
}
float FuelFlow()
{
return throttleSetting * 10.0;
}
void SetThrottle(float setting)
{
throttleSetting = setting
}
void RunModel() // from SimModel base class
{
if(throttleSetting > 0.5)
rpm += 1;
else
rpm -= 1;
}
private:
float rpm, throttleSetting;
};
class Continental350: public EngineModelInterface
{
public:
float RPM()
{
return rand();
}
float FuelFlow()
{
return rand;
}
void SetThrottle(float setting)
{
}
void RunModel() // from SimModel base class
{
}
};
Now, here's some code where somebody wants an engine:
.
.
EngineModelInterface * eng = simDB.FindModel<EngineModelInterface *>();
.
.
fuel = fuel - deltaTime * eng->FuelFlow();
.
.
.
Code is pretty pseudo, but I hope it gets the idea across. One developer can write code that depends on having an Engine, but as long as it has something that implements the engine interface, it doesn't care what it is. So the code that updates the amount of fuel in the tanks is completely decoupled from everything except the FindModel<>() function, and the pure virtual EngineModel interface that he's interested in using. Somebody a year later can make a new engine model, register it with the SimulationDatabase, and the guy above who updates fuel will start using it automatically. I actually made it so you could load new models as plugins (DLLs) at runtime, and once they are registered in the SimulationDatabase, they could be found with FindModel<>(), even though the code that was looking for them was compiled and built into a DLL months before the new DLL existed. You could also add new Interfaces that derive from SimModel, with something that implements them in one DLL, something that searches for them in another DLL, and once you load both DLLs, one can do a FindModel<>() to get the model in the other. Even though the Interface itself didn't even exist when the main app was built.
Parenthetically, RTTI doesn't always work across DLL boundaries. Since I was using Qt anyway, I used qobject_cast instead of dynamic_cast. Every class had to inherit from QObject (and get moc'd), but the qobject meta-data was always available. If you don't care about DLLs, or you are using a toolchain where RTTI does work across DLL boundaries (type comparisons based on string comparisons instead of hashes or whatever), then all of the above with dynamic_cast will work just fine.
I use it in a class tree which serializes to a XML file. On the de-serialization, the parser class returns a pointer to the base class which has a enumeration for the type of the subclass (because you don't know which type it is until you parse it). If the code using the object needs to reference subclass specific elements, it switches on the enum value and dynamic_cast's to the subclass (which was created by the parser). This way the code can check to ensure that the parser didn't have an error and a mismatch between the enum value and the class instance type returned. Virtual functions are also not sufficient because you might have subclass specific data you need to get to.
This is just one example of where RTTI could be useful; it's perhaps not the most elegant way to solve the problem, but using RTTI makes the application more robust when using this pattern.
Sometimes static_cast and C-style casts just aren't enough and you need dynamic_cast, an example of this is when you have the dreaded diamond shaped hierarchy (image from Wikipedia).
struct top {
};
struct left : top {
int i;
left() : i(42) {}
};
struct right : top {
std::string name;
right() : name("plonk") { }
};
struct bottom : left, right {
};
bottom b;
left* p = &b;
//right* r = static_cast<right*>(p); // Compilation error!
//right* r = (right*)p; // Gives bad pointer silently
right* r = dynamic_cast<right*>(p); // OK
Use cases I have in my projects (if you know any better solution for specific cases, please comment):
The same thing as 1800 INFORMATION has already mentioned:
You'll need a dynamic_cast for the operator== or operator< implementation for derived classes. Or at least I don't know any other way.
If you want to implement something like boost::any or some other variant container.
In one game in a Client class which had a std::set<Player*> (possible instances are NetPlayer and LocalPlayer) (which could have at most one LocalPlayer), I needed a function LocalPlayer* Client::localPlayer(). This function is very rarely used so I wanted to avoid to clutter Client with an additional local member variable and all the additional code to handle this.
I have some Variable abstract class with several implementations. All registered Variables are in some std::set<Variable*> vars. And there are several builtin vars of the type BuiltinVar which are saved in a std::vector<BuiltinVar> builtins. In some cases, I have a Variable* and need to check if it is a BuiltinVar* and inside builtins. I could either do this via some memory-range check or via dynamic_cast (I can be sure in any case that all instances of BuiltinVar are in this vector).
I have a gridded collection of GameObjects and I need to check if there is a Player object (a specialized GameObject) inside one grid. I could have a function bool GameObject::isPlayer() which always returns false except for Player or I could use RTTI. There are many more examples like this where people often are implementing functions like Object::isOfTypeXY() and the base class gets very cluttered because of this.
This is also sometimes the case for other very special functions like Object::checkScore_doThisActionOnlyIfIAmAPlayer(). There is some common sense needed to decide when it actually make sense to have such a function in the base class and when not.
Sometimes I use it for assertions or runtime security checks.
Sometimes I need to store a pointer of some data in some data field of some C library (for example SDL or what not) and I get it somewhere else later on or as a callback. I do a dynamic_cast here just to be sure I get what I expect.
I have some TaskManager class which executes some queue of Tasks. For some Tasks, when I am adding them to the list, I want to delete other Tasks of the same type from the queue.
I used RTTI when doing some canvas-based work with Qt several years ago. It was darn convenient when doing hit-tests on objects to employ RTTI to determine what I was going to do with the shape I'd 'hit'. But I haven't used it otherwise in production code.
I'm using it with Dynamic Double Dispatch and Templates. Basically, it gives the ability to observe/listen to only the interesting parts of an object.