Is it a good practice to define algorithm parameter settings as an independent class in C++? - c++

I was wondering whether it was a good practice to define algorithm parameter settings as an independent class. I illustrate my question with the following codes:
using namespace std;
class Parameters
{
public:
Parameters():a_para_(0),b_para_(0) {};
~Parameters() {};
Parameters(const Parameters &para)
{
a_para_ = para.a_para_;
b_para_ = para.b_para_;
}
void set_a_parameter(int a)
{
a_para_ = a;
}
void set_b_parameter(int b)
{
b_para_ = b;
}
private:
int a_para_;
int b_para_;
};
class Algorithm
{
public:
Algorithm() {};
~Algorithm() {};
void set(const Parameters &para)
{
para_ = para;
}
void run()
{
}
private:
Parameters para_;
};
int main()
{
Parameters para;
para.set_a_parameter(3);
para.set_b_parameter(4);
Algorithm fun;
fun.set(para);
fun.run();
return 0;
}
The philosophy behind is that the parameter setting and algorithm implementation can be separated. I discussed this design strategy with an experienced programmer, and it seems that he prefer that the parameter setting and the algorithm should be mixed together as one class. I am therefore writing here for your advice: which one is better? Thanks!

Your question is very general, and there's no general answer. It depends on the situation.
Often times you want to be able to decide at compile time the parameters of your algorithm (for instance, the size of a given buffer, or the dimension of a matrix, or the arity of a tree nodes). Usually these parameters don't change for the lifetime of your algorithm "instance", so to speak. In this context, it is usually good practice to turn your algorithm class into a template, and make these parameters the template parameters.
If the parameters must change during the algorithm lifetime, but their implementation are trivial, there's no need to externalize them. If they are non trivial, and their implementation details may change the algorithm performance (ex: a matrix implementation based on arrays for dense matrices, or on linked lists for sparse ones), then I suppose that you could externalize that parameter.
I think you should ask a more specific question if you want to get a better answer.

Related

How to design a class with methods which have similar functions but different signatures [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
The task I have at hand is to write a system to test out n different algorithms in a library - all doing the same broad task but with different methodologies. I thought about creating a main class to which I send an argument defining the algorithm to be used. This main class in-turn calls the taskAlgorithm class passing on the parameter to be used and the required input parameters for the algorithm to be used. The taskAlgorithm class should then instantiate the specific algorithm class to be used in its constructor. taskAlgorithm::Process should run the algorithm and store the result and taskAlgorithm::Result should return the result.
I am stuck on figuring out how to write this taskAlgorithm class. In the constructor of this class, based on the algorithmCode parameter I want to instantiate an object of the specific algorithm, however, all algorithm classes are different and do not necessarily have a common base class. What's the best way to tackle this problem?
Specifically in
taskAlgorithm::taskAlgorithm(int algorithmCode, int argument1){
if(algorithmCode == 1){
//instantiate the algorithm1 object
}
else if(algorithmCode == 2){
//instantiate algorithm2 object
}
}
how should I instantiate objects for each of different algorithm classes if they don't necessarily share a common base class?
If they are related algorithms, perhaps you can think of the "common" interface that, if it existed, would be capable of calling into any of the algorithms if you knew which parts to use, or which transformations to perform.
This would allow you to write a wrapper interface to all the algorithms, so they can be called uniformly. Each wrapper could "know" how to take its inputs to call the underlying algorithm that it wraps. I didn't do it here, but you could do the same for the return value.
For example Algorithm A is a sort taking a pair of iterators into a vector of ints, and a comparator, while Algorithm B is a different kind of sort, taking a pointer to an int array, a length, and a comparator.
class Algo {
public:
using Iter = std::vector<int>::iterator;
using Compare = ...;
virtual void call(Iter b, Iter e, Compare comp) = 0;
virtual ~Algo() = default;
};
class A : public Algo {
void call(Iter b, Iter e, Compare comp) override {
algorithmA(b, e, comp);
}
};
class B : public Algo {
void call(Iter b, Iter e, Compare comp) override {
if (b != e) {
algorithmB(&*b, std::distance(b, e), comp);
}
}
};
Now you can wrap algorithm A with class A, and algorithm b with class B, and they are invoked identically, and the wrappers share a common base class so they can be used polymorphicly.
Of course, you can't templatize virtual functions so the iterator type is fixed, but the example here is about making a wrapper hierarchy that normalizes the interface to the algorithms. Then you can avoid a nasty switch statement (which requires editing working code every time you add a new algorithm.) With a class wrapper approach, just wrap new algorithm with a new wrapper class and it should just fit into any system that already works with the existing algorithms (provided you don't change the signature of the virtual call() function).
This isn't exactly answering your question but I think it's close enough to maybe be useful. :)
According to the comments under the question, I think in this case this is the only reasonable approach:
// structure of all possible arguments to all your algorithms
struct AlgorithmArgs {
int arg1;
int arg2; // etc ...
}
class AlgorithmWrapper {
public:
AlgorithmWrapper(int algorithmId, const AlgorithmArgs args) {
if (algorithmId == 1) {
algorithm_ = Algorithm1{}; // or whatever you do to construct that Algorithm1 object
} else if ( /* etc ... */ ) {}
}
void someMethodToUnifyAllAlgorithmInterfaces1();
void someMethodToUnifyAllAlgorithmInterfaces2();
void someMethodToUnifyAllAlgorithmInterfaces3();
private:
std::variant<Algorithm1, Algorithm2, Algorithm3> algorithm_;
};
taskAlgorithm::taskAlgorithm(int algorithmCode, int argument1){
AlgorithmArgs args;
args.arg1 = argument1;
algorithmWrapperPtr_ = new AlgorithmWrapper(algorithmCode, args);
executeSomeUnifiedProcedureCommonForAllAlgorithms();
}

declaring a function virtual slows it down; alternatives?

I have a class called WorkerA that works on one image format (let's just call it A, it's rather non-standard). The class has been working well:
class WorkerA
{
public:
void Setup()
{
//some stuff specific to format A
}
void MainTask()
{
//some algorithm that calls GetPixel() a lot
}
//...
protected:
int GetPixel(int x, int y)
{
int value;
//value = ... (gets pixel value in format A)
return value;
}
unsigned char * pBitmapA;
//...
};
Now I need another class that works on image format B. MainTask and a few other functions are the same as WorkerA, but the remaining function needs different implementations. Unsure of the best practice in this scenario, I hacked together something like the following:
class WorkerB : public WorkerA
{
public:
void Setup()
{
//some stuff specific to format B
}
//... (other functions. MainTask not re-implemented.)
protected:
virtual int GetPixel(int x, int y)
{
int value;
//value = ... (gets pixel value in format B)
return value;
}
unsigned char ** pBitmapB; //different format than pBitmapA
};
By this point, I also made WorkerA::GetPixel virtual, to get the correct polymorphic behavior when I call WorkerB::MainTask. However, this one change caused WorkerA::MainTask to run 50% longer than before -- something I really need to avoid.
My question is: how should I rearrange these 2 classes so that there's as little duplicated code as possible, without the speed penalty? I can completely rewrite WorkerA and WorkerB if necessary (although preferrably I can keep WorkerA's existing interface), but I can't change the image formats.
Generally any imaging code that makes a call for each pixel is going to be slow. If you can, refactor the code so it works with a much larger block, perhaps a raster line at a time.
If you can determine which class to use at compile time rather than run time, you can use the Curiously Recurring Template Pattern (CRTP) to eliminate the overhead of a virtual call.
Not really an answer, but there are themes here worth following.
GetPixel() is a notoriously bad thing from a performance point of view. Seriously consider using algorithms that do not require a heavy dependence on this. Maybe convert it to inline or template or macro if it really has to be.
Are you sure about the benchmarking? The inherent overhead from a virtual function call is a couple of machine instructions, which would not ordinarily cause such a severe impact. Are you sure there isn't something else going on here?
Do you really need virtual? Inheritance is a solution to many problems, not all of which require virtual functions and dynamic binding. Perhaps you can reorganise your code to use static inheritance or templating, at least for a good part of what you need, and avoid the virtual call to GetPixel() entirely.
If you have more info please edit your question accordingly.

How can I switch element and container types for purpose of benchmarking, without producing a large number of test client applications?

I have a ClientInterface class, that uses the Strategy pattern to organize two complex algorithms conforming to interfaces Abase and Bbase, respectively. The ClientInterface agglomerates (via composition) the data on which the algorithms operate, which needs to conform to the Data interface.
What I tried to do is to have a single ClientInterface class, which is able to choose different Strategies and Data implementations at run-time. The algorithms and data implementations are chosen using the Factory Method which reads the strings from an input file and selects the algorithm and data implementation in the ClientInterface constructor. The run-time choice of data and algorithms is not provided in the code model below.
The Data implementation can be based on a map, a list, an unordered_map , etc. to test how does the efficiency of two complex algorithms (Abase and Bbase implemented Strategies) change with different containers used for the Data.
Additionally, the Data agglomerates different Elements (ElementBase implementations). Different element implementations will also have significant impact on the efficiency of theh ClientInterface, but the Elements are really disjoint types with implementations coming from different libraries. I know this for a fact, since profiling the existing application shows the Element operation to be one of the bottlenecks.
I know that if I use polymorphism with containers, there is "boost/ptr_container" out there, but the Data will store hundreds of thousands, if not millions of Elements. Using polymorphism for Elements in this case will have a significant overhead on the ClientInterface, but if I choose to make data a class Template for the Element type, I will end up statically defining the ClientInterface class, which means producing a client application per each Element type at least.
Can I assume that for the same number of Elements and the ClientInterface configuration obtained at run-time, the overhead induced by the use of polymorphism for the Element type will have the same impact on all configurations of the Data and Algorithm implementations? In this case, I can run the automated tests, decide on the configuration of the Data implementation and the Element implementation, and define a statically configured EfficientClientInterface to be used in the productive code?
Goal: I have a test harness prepared, and what I am trying to do is to automatize the testing on the family of test cases, since changing the Algorithms and Elements at run-time, allows me to use a single application in a loop, which is configured at run-time and whose output is measured for efficiency. In the real implementation, I am dealing with at least 6 algorithm interfaces, 3-4 Data implementations, and I estimate 3 Element implementations at least.
So, my questions are:
1) How can an Element support different operations when overloading is not working for return types? If I make the operation a template, it needs to be defined at compile-time, which messes with my automated testing procedure.
2) How can I design this code better to achieve the goal?
3) Is there a better overall approach to this problem?
Here is the code model:
#include <iostream>
#include <memory>
class ElementOpResultFirst
{};
class ElementOpResultSecond
{};
class ElementBase
{
public:
// Overloading does not allow different representation of the solution for the element operation.
virtual ElementOpResultFirst elementOperation() = 0;
//virtual ElementOpResultSecond elementOperation() = 0;
};
class InterestingElement
:
public ElementBase
{
public:
ElementOpResultFirst elementOperation()
{
// Implementation dependant operation code.
return ElementOpResultFirst();
}
//ElementOpResultSecond elementOperation()
//{
//// Implementation dependant operation code.
//return ElementOpResultSecond();
//}
};
class EfficientElement
:
public ElementBase
{
public:
ElementOpResultFirst elementOperation()
{
// Implementation dependant operation code.
return ElementOpResultFirst();
}
//ElementOpResultSecond elementOperation()
//{
//// Implementation dependant operation code.
//return ElementOpResultSecond();
//}
};
class Data
{
public:
virtual void insertElement(const ElementBase&) = 0;
virtual const ElementBase& getElement(int key) = 0;
};
class DataConcreteMap
:
public Data
{
// Map implementation
public:
void insertElement(const ElementBase&)
{
// Insert element into the Map implementation.
}
const ElementBase& getElement(int key)
{
// Get element from the Map implementation.
}
};
class DataConcreteVector
:
public Data
{
// Vector implementation
public:
void insertElement(const ElementBase&)
{
// Insert element into the vector implementation.
}
const ElementBase& getElement(int key)
{
// Get element from the Vector implementation
}
};
class Abase
{
public:
virtual void aFunction() = 0;
};
class Aconcrete
:
public Abase
{
public:
virtual void aFunction()
{
std::cout << "Aconcrete::function() " << std::endl;
}
};
class Bbase
{
public:
virtual void bFunction(Data& data) = 0;
};
class Bconcrete
:
public Bbase
{
public:
virtual void bFunction(Data& data)
{
data.getElement(0);
std::cout << "Bconcrete::function() " << std::endl;
}
};
// Add a static abstract factory for algorithm and data generation.
class ClientInterface
{
std::unique_ptr<Data> data_;
std::unique_ptr<Abase> algorithmA_;
std::unique_ptr<Bbase> algorithmB_;
public:
ClientInterface()
:
// A Factory Method is defined for Data, Abase and Bbase that
// produces the concrete type based on an entry in a text-file.
data_ (std::unique_ptr<Data> (new DataConcreteMap())),
algorithmA_(std::unique_ptr<Abase> (new Aconcrete())),
algorithmB_(std::unique_ptr<Bbase> (new Bconcrete()))
{}
void aFunction()
{
return algorithmA_->aFunction();
}
void bFunction()
{
return algorithmB_->bFunction(*data_);
}
};
// Single client code: both for testing and final version.
int main()
{
ClientInterface cli;
cli.aFunction();
cli.bFunction();
return 0;
};
What I tried to do is to have a single ClientInterface class, which is
able to choose different Strategies and Data implementations at
run-time. The algorithms and data implementations are chosen using the
Factory Method which reads the strings from an input file and selects
the algorithm and data implementation in the ClientInterface
constructor. The run-time choice of data and algorithms is not
provided in the code model below.
Sounds like you have the basis for some of it here: Either just produce a set of files to test with that produce the right different sets of inputs. Or refactor the Factory function so that the reading of the file and the strings are separate, so you can call your factory function [internals] with a a string from the code.
Can I assume that for the same number of Elements and the
ClientInterface configuration obtained at run-time, the overhead
induced by the use of polymorphism for the Element type will have the
same impact on all configurations of the Data and Algorithm
implementations? In this case, I can run the automated tests, decide
on the configuration of the Data implementation and the Element
implementation, and define a statically configured
EfficientClientInterface to be used in the productive code?
I don't think you can make that assumption. Different implementations may well have different effects on the algorithms - copying a 100 byte string is significantly harder than copying a 4 byte integer, for example. So what the data is, and how it's organized will have some effect on the work you do. Of course, since you haven't described in much detail what your Elements actually contain, it's all guesswork.
1) How can an Element support different operations when overloading is
not working for return types? If I make the operation a template, it
needs to be defined at compile-time, which messes with my automated
testing procedure.
Make a factory class that returns an ElementBase reference or pointer? That's my immediate reaction to this question, but again, the detail in your question is sufficiently vague that it's hard to say for sure.
In the real application, how does this work? Is it done by templates, then you'd better implement the testcode by templates, and fill it out with a selection of realistic variations on what you think the real system is likely to do.
2) How can I design this code better to achieve the goal?
Try to reuse the production code?
3) Is there a better overall approach to this problem?
Not sure yet.

Most effective method of executing functions an in unknown order

Let's say I have a large, between 50 and 200, pool of individual functions whose job it is to operate on a single object and modify it. The pool of functions is selectively put into a single array and arranged in an arbitrary order.
The functions themselves take no arguments outside of the values present within the object it is modifying, and in this way the object's behavior is determined only by which functions are executed and in what order.
A way I have tentatively used so far is this, which might explain better what my goal is:
class Behavior{
public:
virtual void act(Object * obj) = 0;
};
class SpecificBehavior : public Behavior{
// many classes like this exist
public:
void act(Object * obj){ /* do something specific with obj*/ };
};
class Object{
public:
std::list<Behavior*> behavior;
void behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
iter->act(this);
++iter;
};
};
};
My Question is, what is the most efficient way in C++ of organizing such a pool of functions, in terms of performance and maintainability. This is for some A.I research I am doing, and this methodology is what most closely matches what I am trying to achieve.
edits: The array itself can be changed at any time by any other part of the code not listed here, but it's guaranteed to never change during the call to behave(). The array it is stored in needs to be able to change and expand to any size
If the behaviour functions have no state and only take one Object argument, then I'd go with a container of function objects:
#include <functional>
#include <vector>
typedef std::function<void(Object &)> BehaveFun;
typedef std::vector<BehaveFun> BehaviourCollection;
class Object {
BehaviourCollection b;
void behave() {
for (auto it = b.cbegin(); it != b.cend(); ++it) *it(*this);
}
};
Now you just need to load all your functions into the collection.
if the main thing you will be doing with this collection is iterating over it, you'll probably want to use a vector as dereferencing and incrementing your iterators will equate to simple pointer arithmetic.
If you want to use all your cores, and your operations do not share any state, you might want to have a look at a library like Intel's TBB (see the parallel_for example)
I'd keep it exactly as you have it.
Perofmance should be OK (there may be an extra indirection due to the vtable look up but that shouldn't matter.)
My reasons for keeping it as is are:
You might be able to lift common sub-behaviour into an intermediate class between Behaviour and your implementation classes. This is not as easy using function pointers.
struct AlsoWaveArmsBase : public Behaviour
{
void act( Object * obj )
{
start_waving_arms(obj); // Concrete call
do_other_action(obj); // Abstract call
end_waving_arms(obj); // Concrete call
}
void start_waving_arms(Object*obj);
void end_waving_arms(Object*obj);
virtual void do_other_actions(Object * obj)=0;
};
struct WaveAndWalk : public AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
};
struct WaveAndDance : pubic AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
}
You might want to use state in your behaviour
struct Count : public Behavior
{
Behaviour() : i(0) {}
int i;
void act(Object * obj)
{
count(obj,i);
++i;
}
}
You might want to add helper functions e.g. you might want to add a can_act like this:
void Object::behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
if( iter->can_act(this) ){
iter->act(this);
}
++iter;
};
};
IMO, these flexibilities outweigh the benefits of moving to a pure function approach.
For maintainability, your current approach is the best (virtual functions). You might get a tiny little gain from using free function pointers, but I doubt it's measurable, and even if so, I don't think it is worth the trouble. The current OO approach is fast enough and maintainable. The little gain I'm talking about comes from the fact that you are dereferencing a pointer to an object and then (behind the scenes) dereferencing a pointer to a function (which happening as the implementation of calling a virtual function).
I wouldn't use std::function, because it's not very performant (though that might differ between implementations). See this and this. Function pointers are as fast as it gets when you need this kind of dynamism at runtime.
If you need to improve the performance, I suggest to look into improving the algorithm, not this implementation.

Testing a c++ class for features

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);
}