This is my first question here, so hopefully it's a good one (I have searched for an answer, but not found it yet).
I have an event based disease model written in C++, and I'm trying to convert it to OOP (partly for my own learning experience). The basic class (Herd) stores numbers of susceptible, infective, and resistant animals, and the rates at which possible events occur.
class Herd {
private:
int S,I,R,N;
float birth, death, infection, recovery, movement;
public:
void calc_birth(void) { birth = r*N*(1.0-N/c); }
void calc_infection(void) { infection = N>0 ? beta*S*I/N : 0.0; }
// etc.
};
I then have a vector of herds to keep track of. Throughout this model I will need to calculate the sum of each member across all herd, after an event changes the number or category of individuals in a herd (this happens a lot). I already have 4 categories and 5 events, and this model could easily be expanded and require considerably more.
In my old, procedural code, I simply had a separate vector for each member, and it was easy to create a sum() function to calculate the results, but I can't see how to do this with a class without writing a separate sum function for each member (which is possible, but I doubt it's a particularly good way of doing it). I could make a static member (e.g. sum_S) to track the total, and update it every time an event occurs but this might not be appropriate for all members, and I'm not sure if the total might not slowly wander away from the true value when it comes to the rates.
Is there a way to write a single sum() function, which takes the member I want as a parameter, and returns the sum of that particular member across all the herds?
Thank you!
The standard library header numeric contains the function accumulate. It does not do exactly what you want, but is easily adaptable:
#include <numeric>
#include <vector>
#include <iostream>
struct Foo {
int member;
};
int main()
{
std::vector<Foo> v = { {1}, {2}, {3} };
int sum
= std::accumulate(begin(v), end(v), 0,
// lambda that sums up
[](const int& x, const Foo& y)
{return x + y.member;});
std::cout << sum << std::endl;
return 0;
}
The code uses initializer_lists and lambdas. If those aren't supported by your compiler, use the corresponding C++03 code (push_back and functors).
Sure, using pointer-to-members.
float sum_for_member( std::vector< Herd > const &herds, float Herd::*member ) {
float acc = 0;
for ( std:vector< Herd >::const_iterator it = herds.begin();
it != herds.end(); ++ it ) {
acc += (*it).*member;
}
return acc;
}
to call it:
float total_recovery = sum_for_member( my_herds, & Herd::recovery );
If you want to use a member function getRecovery instead, the parameter declaration becomes float (Herd::*member)() and the summation becomes acc += ((*it).*member)().
If you're not afraid to get further from OO and into generic C++ style, you can use a function template and let the Standard Library take care of the loop:
template< float Herd::*member >
float plus( float lhs, Herd const &rhs )
{ return lhs + rhs.*member; }
vector< Herd > h;
std::accumulate( h.begin(), h.end(), 0., plus< & Herd::recovery > );
So this is what I ended up with (inside a class called State, which holds the simulation state including a vector<Herd>):
Class State {
...
template <typename T>
T sum(T (Herd::*getter)()) {
T acc = (T) 0.0;
for (int i=0; i<size; ++i) {
acc += (herds[i].*getter)();
}
return acc;
...
}
This works for both the numbers of individuals (ints) and the event rates (floats), and uses pointers to member functions to keep those values private. An example of how this is called in the code is:
cout << "total # of S = " << state.sum(&Herd::getS)
"total # of I = " << state.sum(&Herd::getI)
"total birth rate = " << state.sum(&Herd::get_birth)
"total infection rate = " << state.sum(&Herd::get_infection)
etc.
Thanks very much for your help, especially to Potatoswatter. This is much better than the tedious boilerplate code I had before!
Related
Basically i've only realised that the way i've coded my project i need to implement some form of lookup table, now i have never done this before and therefore don't know how to do it and googling doesn't really give a clear set of instructions
I need the lookup table so that a user can input a function into the command line and then pass in parameters to that function, but no idea where to start
You could do something like this in order to create a lookup (dispatch) table:
(Notice: This is how to implement a dispatch table and it is both C and C++ compartible. There are other-and maybe easier ways to do this in C++ without reinventing the wheel, like using some containers etc).
#include <iostream>
using namespace std;
// Arrays start from 0.
// This is used for code
// readability reasons.
#define CASE(X) X-1
typedef void (*chooseCase)();
// Functions to execute each case.
// Here, I am just printing
// different strings.
void case1(){
cout<< "case1" << endl;
}
void case2(){
cout<< "case2" << endl;
}
void case3(){
cout<< "case3" << endl;
}
void case4(){
cout<< "case4" << endl;
}
//Put all the cases in an array.
chooseCase cases[] = {
case1, case2, case3, case4
};
int main()
{
//You can call each scenario
//by hand easily this way:
cases[CASE(1)]();
cout << endl;
//Idea: You can even set in another
// array a sequence of function executions desired.
int casesSequence[] = {
CASE(1), CASE(2), CASE(3), CASE(4),CASE(3),CASE(2),CASE(1)
};
//Execute the functions in the sequence set.
for(int i = 0; i < (sizeof(casesSequence)/sizeof(int)); ++i){
cases[casesSequence[i]]();
}
return 0;
}
(Based on: Adding split-screen multiplayer to c++ game)
Now about the program input, you could map the name of your function to get the index for example and you could apply the example above to parameterized functions and you can also use this in situations that functions are parameterized.
In this case,please take into consideration that all functions should obey to the function pointer signature in order to use it in this example. Otherwise, you have to do more tricky things (like using a void* argument and passing an arguments struct "instance" pointer to each function).
I don't know exactly your requirements, but I could imagine sth like this:
You might want to have a look into C++ function pointers. You could make an own struct that holds:
name of a function
pointer to that function
vector of variants (for example from boost or write yourown) to hold the arguments
validate function to see if the arguments and function pointer fit
Create for each function that the user can call a an instance of this struct. Display those to the user and let him choose. In the second step, let him enter the values for the arguments.
You can use std::map<std::string, functype> where functype is a typedef'd function pointer, or even a boost::function<> type.
std::map<std::string, functype> funcs;
void call_user_func(const std::string &user_input, const std::string &arg1, const std::string & arg2)
{
functype f = funcs.at(user_input);
f(arg1, arg2);
}
I give you and example on Arduino that is almost the same C/C++ code analogy
float cosLUT[(int) (360.0 * 1 / 0.5)] ;
const float DEG2RAD = 180 / PI ;
const float cosinePrecision = 0.5;
const int cosinePeriod = (int) (360.0 * 1 / cosinePrecision);
void setup()
{
initCosineLUT();
}
void loop()
{
// nothing for now!
}
void initCosineLUT(){
for (int i = 0 ; i < cosinePeriod ; i++)
{
cosLUT[i] = (float) cos(i * DEG2RAD * cosinePrecision);
}
}
Lookup tables are one of the most powerful tricks in the programming universe.
They are arrays containing precalculated values and thus replace heavy runtime
calculations by a simpler array index operation. For instance, imagine you want to
track positions of something by reading distances coming from a bunch of distance
sensors. You'll have trigonometric and probably power calculations to perform.
Because they can be time consuming for your processor, it would be smarter and
cheaper to use array content reading instead of those calculations. This is the usual
illustration for the use of lookup tables.
As the question asks...
What is the difference between:
class MyClass
{
public:
MyClass(){
m_a = 0;
}
private:
int m_a;
friend void set_a(MyClass &a);
};
void set_a(MyClass &a)
{
std::cout << a.m_a << std::endl;
a.m_a = 500;
std::cout << a.m_a << std::endl;
}
int main(void) {
MyClass my_class_instance;
set_a(my_class_instance);
system("pause");
}
and:
class MyClass
{
public:
MyClass(){
m_a = 0;
}
void set_a(){
std::cout << this->m_a << std::endl;
this->m_a = 500;
std::cout << this->m_a << std::endl;
}
private:
int m_a;
};
int main(void) {
MyClass my_class_instance;
my_class_instance.set_a();
system("pause");
}
Is it simply the preferred structure of the function, or are there real, measurable differences? From what I can tell, both functions achieve the same results in all circumstances, except if you had multiple overloads for the first example, that took different types of objects.
As the C++ FAQ says: Use a member when you can, and a friend when you have to.
There are situations where making friend a free function is preferable, most situations related to the fact that the first parameter of a member function is always of that class (Its the hidden *this parameter).
One example is arithmetic operators overloading:
Suppose you write a complex class which represents complex numbers. Using a member operator+() you could write expressions like complex + float, but not float + complex. But you could do it with the free form of the operator+:
class complex
{
...
friend complex operator+( float f , complex c );
};
This whole question comes down to "Why would I use friends in C++?". The answer is that when used properly, friends enhance encapsulation. This is an FAQ:
Do friends violate encapsulation?
Your example is too short and too abstract, of course. Some better, real life examples I could think of from the top of my head involve iterators. You may have many iterator objects referring to only one container object, and you may want the iterator to be able to access private member variables of the container. At the same time, you don't want the container to expose those variables to the rest of the world.
Such a design could be perfectly implemented with the friend feature.
Many people defend that making accessor methods, you can in a later stage of development put barriers to the incorrect access to the member variables (or even change the member variables totally) without breaking your (correct) clients.
One classical case is of a
class ComplexNumber {
double real, imaginary;
public:
double re() { return re; }
double setRe(double v) { return re = v; }
// and so on ...
};
one day you discover, in some maintenance, that you need the polar coordinates for that number, so you add the methods
double rho() { /* calculate rho */ }
double theta() { /* calculate theta */ }
double setRho(double v) { /* calculate real, imaginary, based on the new rho */ }
and so on.
Later yet, you discover that the users of the class use far more often polar than Cartesian coordinates for complex numbers, and that the conversions have been the bottleneck of a performance problem, so you ditch real and imaginary and store rho and theta, and change the getter and setter methods for the new -- more efficient -- storage for rho, theta, re, im, and so on. All the clients of your class will recompile without problems, because you changed your implementation but kept your interfaces stable.
I am currently designing an API where I want that the user to be able to write code like this:
PowerMeter.forceVoltage(1 mV);
PowerMeter.settlingTime(1 ms);
Currently we do this using defines like:
#define mV *1.0e-03
This makes it very convenient for the user to write their code and it is also very readable, but of course has also drawbacks:
int ms;
Will throw some compiler errors which are hard to understand. So I am looking for a better solution.
I tried the new C++11 literals, but with this all I could achieve is:
long double operator "" _mV(long double value) {
return value * 1e-3;
}
PowerMeter.forceVoltage(1_mV);
In the end the API does not care about the unit like Volt or second but only takes the number, so I don't want to do any checking if you really input Volts in forceVoltage or not. So this should also be possible:
PowerMeter.forceVoltage(2 ms);
Any idea besides staying with the defines?
how about instead turning it around a bit by creating classes (ms,mV) for the different currents
e.g.
PowerMeter.forceVoltage( mV(1) );
PowerMeter.settlingTime( ms(1) )
It is pretty clear to the user and arguably not hard to read plus you would get type checking for free. having a common base class for the different units would make it easier to implement.
You can see the library "C++ Units" from Calum Grant as a good example of how to implement this. The library is a bit outdated, but still worth to see or may be to use.
Also, i think it might be interesting to read: "Applied Template Metaprogramming in
SI UNITS: the Library of Unit-Based Computation"
There is one more good library: UDUNITS-2 which:
contains a C library for units of physical quantities and a unit-definition and value-conversion utility.
You could use C++11's compile-time rational arithmetic support for the units, instead of defining literals or macros for the units.
Take a look at Boost.Units.
Here's some example code:
quantity<energy>
work(const quantity<force>& F, const quantity<length>& dx)
{
return F * dx; // Defines the relation: work = force * distance.
}
...
/// Test calculation of work.
quantity<force> F(2.0 * newton); // Define a quantity of force.
quantity<length> dx(2.0 * meter); // and a distance,
quantity<energy> E(work(F,dx)); // and calculate the work done.
I prefer avoiding macros where ever I can, and this is an example where it should be possible.
One lightweight solution that gives you correct dimensions would be:
static double m = 1;
static double cm = 0.1;
static double mV = 0.001;
double distance = 10*m + 10*cm;
This also reflects the physical concept that units are something that's multiplied with the value.
Here's what I came up with... pretty much the same idea as Anders K, but since I wrote the code, I'll post it:
#include <iostream>
using namespace std;
class MilliVoltsValue;
class VoltsValue;
class VoltsValue
{
public:
explicit VoltsValue(float v = 0.0f) : _volts(v) {/* empty */}
VoltsValue(const MilliVoltsValue & mV);
operator float() const {return _volts;}
private:
float _volts;
};
class MilliVoltsValue
{
public:
explicit MilliVoltsValue(float mV = 0.0f) : _milliVolts(mV) {/* empty */}
MilliVoltsValue(const VoltsValue & v) : _milliVolts(v*1000.0f) {/* empty */}
operator float() const {return _milliVolts;}
private:
float _milliVolts;
};
VoltsValue :: VoltsValue(const MilliVoltsValue & mV) : _volts(mV/1000.0f) {/* empty */}
class PowerMeter
{
public:
PowerMeter() {/* empty */}
void forceVoltage(const VoltsValue & v) {_voltsValue = v;}
VoltsValue getVoltage() const {return _voltsValue;}
private:
VoltsValue _voltsValue;
};
int main(int argc, char ** argv)
{
PowerMeter meter;
meter.forceVoltage(VoltsValue(5.0f));
cout << "Current PowerMeter voltage is " << meter.getVoltage() << " volts!" << endl;
meter.forceVoltage(MilliVoltsValue(2500.0f));
cout << "Now PowerMeter voltage is " << meter.getVoltage() << " volts!" << endl;
// The line below will give a compile error, because units aren't specified
meter.forceVoltage(3.0f); // error!
return 0;
}
Consider using an enum for your units and pass it as a second parameter:
namespace Units
{
enum Voltage
{
millivolts = -3,
volts = 0,
kilovolts = 3
};
enum Time
{
microseconds = -6,
milliseconds = -3,
seconds = 0
};
}
class PowerMeter
{
public:
void forceVoltage(float baseValue, Units::Voltage unit)
{
float value = baseValue * std::pow(10, unit);
std::cout << "Voltage forced to " << value << " Volts\n";
}
void settlingTime(float baseValue, Units::Time unit)
{
float value = baseValue * std::pow(10, unit);
std::cout << "Settling time set to " << value << " seconds\n";
}
}
int main()
{
using namespace Units;
PowerMeter meter;
meter.settlingTime(1.2, seconds);
meter.forceVoltage(666, kilovolts);
meter.forceVoltage(3.4, milliseconds); // Compiler Error
}
Wrapping the Units namespace around the enums avoids polluting the global namespace with the unit names. Using enums in this way also enforces at compile time that the proper physical unit is passed to the member functions.
I prefer the solution from Anders K, however you may use a template to save some time implementing all units as a separte class which can be timeconsuming and prone to errors as you may need to write a lot of code by hand:
enum Unit {
MILI_VOLT = -3,
VOLT = 0,
KILO_VOLT = 3
};
class PowerMeter
{
public:
template<int N>
void ForceVoltage(double val)
{
std::cout << val * pow(10.0, N) << endl;
};
};
Use like this:
PowerMeter pm;
pm.ForceVoltage<MILI_VOLT>(1);
pm.ForceVoltage<VOLT>(1);
pm.ForceVoltage<KILO_VOLT>(1);
Before you go crazy with anything more complicated, whenever you write new code that takes a quantity as an argument you should name your methods like this so that it's 100% clear:
PowerMeter.forceInMilliVolts( ... )
PowerMeter.settlingTimeInSeconds( ... )
And similarly use variables with the right names e.g.:
int seconds(10);
int milliVolts(100);
This way it does not matter if you have to convert, it is still clear what you are doing e.g.
PowerMeter.settlingTimeInSeconds( minutes*60 );
When you are ready with something more powerful move to that, if you really need to, but make sure you do not lose the clarity of which unit is being used.
I'm trying create a class which adds functionality to a generic class, without directly interfacing with the wrapped class. A good example of this would be a smart pointer. Specifically, I'd like to create a wrapper which caches all the i/o for one (or any?) method invoked through the wrapper. Ideally, the cache wrapper have the following properties:
it would not require the wrapping class to be changed in any way (i.e. generic)
it would not require the wrapped class to be changed in any way (i.e. generic)
it would not change the interface or syntax for using the object significantly
For example, it would be really nice to use it like this:
CacheWrapper<NumberCruncher> crunchy;
...
// do some long and ugly calculation, caching method input/output
result = crunchy->calculate(input);
...
// no calculation, use cached result
result = crunchy->calculate(input);
although something goofy like this would be ok:
result = crunchy.dispatch (&NumberCruncher::calculate, input);
I feel like this should be possible in C++, although possibly with some syntactic gymnastics somewhere along the line.
Any ideas?
I think I have the answer you are seeking, or, at least, I almost do. It uses the dispatch style you suggested was goofy, but I think it meets the first two criteria you set forth, and more or less meets the third.
The wrapping class does not have to be modified at all.
It doesn't modify the wrapped class at all.
It only changes the syntax by introducing a dispatch function.
The basic idea is to create a template class, whose parameter is the class of the object to be wrapped, with a template dispatch method, whose parameters are the argument and return types of a member function. The dispatch method looks up the passed in member function pointer to see if it has been called before. If so, it retrieves the record of previous method arguments and calculated results to return the previously calculated value for the argument given to dispatch, or to calculate it if it is new.
Since what this wrapping class does is also called memoization, I've elected to call the template Memo because that is shorter to type than CacheWrapper and I'm starting to prefer shorter names in my old age.
#include <algorithm>
#include <map>
#include <utility>
#include <vector>
// An anonymous namespace to hold a search predicate definition. Users of
// Memo don't need to know this implementation detail, so I keep it
// anonymous. I use a predicate to search a vector of pairs instead of a
// simple map because a map requires that operator< be defined for its key
// type, and operator< isn't defined for member function pointers, but
// operator== is.
namespace {
template <typename Type1, typename Type2>
class FirstEq {
FirstType value;
public:
typedef std::pair<Type1, Type2> ArgType;
FirstEq(Type1 t) : value(t) {}
bool operator()(const ArgType& rhs) const {
return value == rhs.first;
}
};
};
template <typename T>
class Memo {
// Typedef for a member function of T. The C++ standard allows casting a
// member function of a class with one signature to a type of another
// member function of the class with a possibly different signature. You
// aren't guaranteed to be able to call the member function after
// casting, but you can use the pointer for comparisons, which is all we
// need to do.
typedef void (T::*TMemFun)(void);
typedef std::vector< std::pair<TMemFun, void*> > FuncRecords;
T memoized;
FuncRecords funcCalls;
public:
Memo(T t) : memoized(t) {}
template <typename ReturnType, typename ArgType>
ReturnType dispatch(ReturnType (T::* memFun)(ArgType), ArgType arg) {
typedef std::map<ArgType, ReturnType> Record;
// Look up memFun in the record of previously invoked member
// functions. If this is the first invocation, create a new record.
typename FuncRecords::iterator recIter =
find_if(funcCalls.begin(),
funcCalls.end(),
FirstEq<TMemFun, void*>(
reinterpret_cast<TMemFun>(memFun)));
if (recIter == funcCalls.end()) {
funcCalls.push_back(
std::make_pair(reinterpret_cast<TMemFun>(memFun),
static_cast<void*>(new Record)));
recIter = --funcCalls.end();
}
// Get the record of previous arguments and return values.
// Find the previously calculated value, or calculate it if
// necessary.
Record* rec = static_cast<Record*>(
recIter->second);
typename Record::iterator callIter = rec->lower_bound(arg);
if (callIter == rec->end() || callIter->first != arg) {
callIter = rec->insert(callIter,
std::make_pair(arg,
(memoized.*memFun)(arg)));
}
return callIter->second;
}
};
Here is a simple test showing its use:
#include <iostream>
#include <sstream>
#include "Memo.h"
using namespace std;
struct C {
int three(int x) {
cout << "Called three(" << x << ")" << endl;
return 3;
}
double square(float x) {
cout << "Called square(" << x << ")" << endl;
return x * x;
}
};
int main(void) {
C c;
Memo<C> m(c);
cout << m.dispatch(&C::three, 1) << endl;
cout << m.dispatch(&C::three, 2) << endl;
cout << m.dispatch(&C::three, 1) << endl;
cout << m.dispatch(&C::three, 2) << endl;
cout << m.dispatch(&C::square, 2.3f) << endl;
cout << m.dispatch(&C::square, 2.3f) << endl;
return 0;
}
Which produces the following output on my system (MacOS 10.4.11 using g++ 4.0.1):
Called three(1)
3
Called three(2)
3
3
3
Called square(2.3)
5.29
5.29
NOTES
This only works for methods which take 1 argument and return a result. It doesn't work for methods which take 0 arguments, or 2, or 3, or more arguments. This shouldn't be a big problem, though. You can implement overloaded versions of dispatch which take different numbers of arguments up to some reasonable max. This is what the Boost Tuple library does. They implement tuples of up to 10 elements and assume most programmers don't need more than that.
The possibility of implementing multiple overloads for dispatch is why I used the FirstEq predicate template with the find_if algorithm instead of a simple for loop search. It is a little more code for a single use, but if you are going to do a similar search multiple times, it ends up being less code overall and less chance to get one of the loops subtlely wrong.
It doesn't work for methods returning nothing, i.e. void, but if the method doesn't return anything, then you don't need to cache the result!
It doesn't work for template member functions of the wrapped class because you need to pass an actual member function pointer to dispatch, and an un-instantiated template function doesn't have a pointer (yet). There may be a way around this, but I haven't tried much yet.
I haven't done much testing of this yet, so it may have some subtle (or not-so-subtle) problems.
I don't think a completely seamless solution which satisfies all your requirements with no change in syntax at all is possible in C++. (though I'd love to be proven wrong!) Hopefully this is close enough.
When I researched this answer, I got a lot of help from this very extensive write up on implementing member function delegates in C++. Anyone who wants to learn way more than they realized was possible to know about member function pointers should give that article a good read.
I don't think this can be easily done using just a wrapper as you'll have to intercept the IO calls, so wrapping a class would put the code at the wrong layer. In essence, you want to substitute the IO code underneath the object, but you're trying to do it from the top layer. If you're thinking of the code as an onion, you're trying to modify the outer skin in order to affect something two or three layers in; IMHO that suggests the design might need a rethink.
If the class that you're trying to wrap/modify this way does allow you to pass in the stream (or whatever IO mechanism you use), then substituting that one for a caching one would be the right thing to do; in essence that would be what you'd be trying to achieve with your wrapper as well.
It looks like a simple task, assuming the "NumberCruncher" has a known interface, let's say int operator(int).
Note that you'll need to make it more complicated to support other interfaces. In order to do so, i'm adding another template parameter, an Adaptor. Adaptor should convert some interface to a known interface. Here's simple and dumb implementation with static method, which is one way to do it. Also look what Functor is.
struct Adaptor1 {
static int invoke(Cached1 & c, int input) {
return(c.foo1(input));
}
};
struct Adaptor2 {
static int invoke(Cached2 & c, int input) {
return(c.foo2(input));
}
};
template class CacheWrapper<typename T, typeneame Adaptor>
{
private:
T m_cachedObj;
std::map<int, int> m_cache;
public:
// add c'tor here
int calculate(int input) {
std::map<int, int>::const_iterator it = m_cache.find(input);
if (it != m_cache.end()) {
return(it->second);
}
int res = Adaptor::invoke(m_cachedObj, input);
m_cache[input] = res;
return(res);
}
};
I think what you need is something like a proxy / decorator (design patterns). You can use templates if you don't need the dynamic part of those patterns. The point is that you need to well define the interface that you will need.
I haven't figured out the case for handling object methods, but I think I've got a good fix for regular functions
template <typename input_t, typename output_t>
class CacheWrapper
{
public:
CacheWrapper (boost::function<output_t (input_t)> f)
: _func(f)
{}
output_t operator() (const input_t& in)
{
if (in != input_)
{
input_ = in;
output_ = _func(in);
}
return output_;
}
private:
boost::function<output_t (input_t)> _func;
input_t input_;
output_t output_;
};
Which would be used as follows:
#include <iostream>
#include "CacheWrapper.h"
double squareit(double x)
{
std::cout << "computing" << std::endl;
return x*x;
}
int main (int argc, char** argv)
{
CacheWrapper<double,double> cached_squareit(squareit);
for (int i=0; i<10; i++)
{
std::cout << cached_squareit (10) << std::endl;
}
}
Any tips on how to get this to work for objects?
I'm working on a fairly complex project, a custom encryption routine if you will (just for fun) and I've run into this issue in designing my code layout.
I have a number of functions that I want to be able to call by index. Specifically, I need to be able to call one randomly for the encrypt process, but then address that by a specific index in the decrypt process.
I was considering a classic function array, but my main concern is that a function array would be tricky to maintain, and a little ugly. (The goal is to get each function pair in a separate file, to reduce compile times and make the code easier to manage.) Does anyone have a more elegant C++ solution as an alternative to a function array? Speed isn't really an issue, I'm more worried about maintainability.
-Nicholas
What's wrong with function array?
You need to call functions by index. So they must be put into some "indexable by index" structure somehow. Array is probably the simplest structure that suits this need.
Example (typing out of my head, might not compile):
struct FunctionPair {
EncodeFunction encode;
DecodeFunction decode;
};
FunctionPair g_Functions[] = {
{ MyEncode1, MyDecode1 },
{ MySuperEncode, MySuperDecode },
{ MyTurboEncode, MyTurboDecode },
};
What is "ugly" or "hard to maintain" in the approach above?
You could write something like:
class EncryptionFunction
{
public:
virtual Foo Run(Bar input) = 0;
virtual ~MyFunction() {}
};
class SomeSpecificEncryptionFunction : public EncryptionFunction
{
// override the Run function
};
// ...
std::vector<EncryptionFunction*> functions;
// ...
functions[2]->Run(data);
You could use operator() instead of Run as the function name, if you prefer.
An object with an operator() method defined can act a lot like a function but be generally nicer to work with.
Polymorphism could do the trick: you couldf follow the strategy pattern, considering each strategy to implement one of your functions (or a pair of them).
Then create a vector of strategies, and use this one instead of the function list.
But frankly, I don't see the problem with the function array; you can easily create a typedef to ease the readability. Effectifely, you will end up with exactly the same file structure when using the strategy pattern.
// functiontype.h
typedef bool (*forwardfunction)( double*, double* );
// f1.h
#include "functiontype.h"
bool f1( double*, double* );
// f1.c
#include "functiontype.h"
#include "f1.h"
bool f1( double* p1, double* p2 ) { return false; }
// functioncontainer.c
#include "functiontype.h"
#include "f1.h"
#include "f2.h"
#include "f3.h"
forwardfunction my_functions[] = { f1, f2, f3 };
The function declaration and definitions are in separate files - compile time is ok.
The function grouping is in a separate file, having a dependency to the declarations only
You could take a look at the Boost.Signals library. I believe it has the ability to call its registered functions using an index.
Try Loki::Functor class. More info at CodeProject.com
You need to use an array of function pointers. The only catch is that all the functions have to have basically the same prototype, only the name of the function and passed argument names can vary. The return type and argument types (as well as the number of arguments and order) must be identical.
int Proto1( void );
int Proto2( void );
int Proto3( void );
int (*functinPointer[3])( void ) =
{
Proto1,
Proto2,
Proto3
};
Then you can do something like this:
int iFuncIdx = 0;
int iRetCode = functinPointer[iFuncIdx++]();
If you looked in boost::signals library, you'll see an example very nice, that is very elegant:
Suppose you have 4 functions like:
void print_sum(float x, float y)
{
std::cout << "The sum is " << x+y << std::endl;
}
void print_product(float x, float y)
{
std::cout << "The product is " << x*y << std::endl;
}
void print_difference(float x, float y)
{
std::cout << "The difference is " << x-y << std::endl;
}
void print_quotient(float x, float y)
{
std::cout << "The quotient is " << x/y << std::endl;
}
Then if you want to call them in a elegant way try:
boost::signal<void (float, float)> sig;
sig.connect(&print_sum);
sig.connect(&print_product);
sig.connect(&print_difference);
sig.connect(&print_quotient);
sig(5, 3);
And the output is:
The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667