How to switch between 2 function sets in C++? - c++

Is there a way, I can switch between 2 similar function sets (C/C++) in an effective way?
To explain better what I mean, lets say I have 2 sets of global functions like:
void a_someCoolFunction();
void a_anotherCoolFunction(int withParameters);
…
void b_someCoolFunction();
void b_anotherCoolFunction(int withParameters);
…
And I want to able to "switch" in my program at runtime which one is used. BUT: I dont want to have one if condition at every function, like:
void inline someCoolFunction(){
if(someState = A_STATE){
a_someCoolFunction();
}else{
b_someCoolFunction();
}
}
Because, I expect that every function is called a lot in my mainloop - so It would be preferable if I could do something like this (at start of my mainloop or when someState is changed):
if(someState = A_STATE){
useFunctionsOfType = a;
}else{
useFunctionsOfType = b;
}
and then simply call
useFunctionsOfType _someCoolFunction();
I hope its understandable what I mean… My Background: Im writing an App, that should be able to handle OpenGL ES 1.1 and OpenGL ES 2.0 both properly - but I dont want to write every render Method 2 times (like: renderOpenGL1() and renderOpenGL2() I would rather to write only render()). I already have similiar Methods like: glLoadIdentity(); myLoadIdentity(); … But need a way to switch between these two somehow.
Is there any way to accomplish this in an efficent way?

Several options, including (but not limited to):
Use function pointers.
Wrap them in classes, and use polymorphism.
Have two separate copies of the loop.
But please profile to ensure this is actually a problem, before you make any large changes to your code.

As the question seems to be interested in a C++ solution and no-one has spelt out the polymorphic solution (too obvious?), here goes.
Define an abstract base class with the API you require, and then implement a derived class for each supported implementation:
class OpenGLAbstract
{
public:
virtual ~OpenGLAbstract() {}
virtual void loadIdentity() = 0;
virtual void someFunction() = 0;
};
class OpenGLEs11 : public OpenGLAbstract
{
public:
virtual void loadIdentity()
{
// Call 1.1 API
}
virtual void someFunction()
{
// Call 1.1 API
}
};
class OpenGLEs20 : public OpenGLAbstract
{
public:
virtual void loadIdentity()
{
// Call 2.0 API
}
virtual void someFunction()
{
// Call 2.0 API
}
};
int main()
{
// Select the API to use:
bool want11 = true;
OpenGLAbstract* gl = 0;
if (want11)
gl = new OpenGLEs11;
else
gl = new OpenGLEs20;
// In the main loop.
gl->loadIdentity();
delete gl;
}
Note that this is exactly the sort of thing that C++ was intended for, so if can use C++ here, this is the simplest way to go.
Now a more subtle issue you might face is if your 2.0 version requires the process to load a dynamic linked library at run time with the 2.0 platform implementation. In that case just supporting the API switch is not enough (whatever the solution). Instead put each OpenGL concrete class in its own linked library and in each provide a factory function to create that class:
OpenGlAbstract* create();
Then load the desired library at run time and call the create() method to access the API.

In C (since it seems you want both C and C++) this is done with pointer to functions.
// Globals. Default to the a_ functions
void(*theCoolFunction)() = a_someCoolFunction;
void(*theOtherCoolFunction)(int) = a_anotherCoolFunction;
// In the code ...
{
...
// use the other functions
theCoolFunction = b_someCoolFunction;
theOtherCoolFunction = b_anotherCoolFunction;
...
}
You might probably want to switch those functions in groups, so you better set a array of pointers to functions and pass that array around. If you decide to do so, you might probably want to also define some macro to ease the reading:
void (*functions_a[2])();
void (*functions_b[2])();
void (**functions)() = functions_a;
....
#define theCoolFunction() functions[0]()
#define theOtherCoolFunction(x) functions[1](x)
....
// switch grooup:
functions = functions_b;
but in this case you'll lose the static check on argument types (and you have to initialize the array, of course).
I guess in C++ you will have instatiate two different objects with the same parent class and different implementation for their methods (but I'm no C++ prograammer!)

You could use functions pointers. You can read a lot about them if you google it, but briefly a function pointer stores a pointer to a function's memory address.
Function pointers can be used the same way as a funcion, but can be assigned the address of different functions, making it a somehow "dynamic" function. As an example:
typedef int (*func_t)(int);
int divide(int x) {
return x / 2;
}
int multiply(int x) {
return x * 2;
}
int main() {
func_t f = ÷
f(2); //returns 1
f = &multiply;
f(2); //returns 4
}

Something like boost::function (std::function) would fit the bill. Using your example:
#include <iostream>
#include <boost/function.hpp> //requires boost installation
#include <functional> //c++0x header
void a_coolFunction() {
std::cout << "Calling a_coolFunction()" << std::endl;
}
void a_coolFunction(int param) {
std::cout << "Calling a_coolFunction(" << param << ")" << std::endl;
}
void b_coolFunction() {
std::cout << "Calling b_coolFunction()" << std::endl;
}
void b_coolFunction(int param) {
std::cout << "Calling b_coolFunction(" << param << ")" << std::endl;
}
float mul_ints(int x, int y) {return ((float)x)*y;}
int main() {
std::function<void()> f1; //included in c++0x
boost::function<void(int)> f2; //boost, works with current c++
boost::function<float(int,int)> f3;
//casts are necessary to resolve overloaded functions
//otherwise you don't need them
f1 = static_cast<void(*)()>(a_coolFunction);
f2 = static_cast<void(*)(int)>(a_coolFunction);
f1();
f2(5);
//switching
f1 = static_cast<void(*)()>(b_coolFunction);
f2 = static_cast<void(*)(int)>(b_coolFunction);
f1();
f2(7);
//example from boost::function documentation. No cast required.
f3 = mul_ints;
std::cout << f3(5,3) << std::endl;
}
Compiled with g++-4.4.4, this outputs:
Calling a_coolFunction()
Calling a_coolFunction(5)
Calling b_coolFunction()
Calling b_coolFunction(7)
15
The biggest limitation is that the types of f1,f2, etc cannot change, so any function you assign to them must have the same signature (i.e. void(int) in the case of f2).

The simple way could be storing pointers to functions, and change them od demand.
But the better way is to use something similar to abstract factory design pattern. The nice generic implementation can be found in Loki library.

In C you would typically do this with a struct containing function pointers:
struct functiontable {
void (*someCoolFunction)(void);
void (*anotherCoolFunction)(int);
};
const struct functiontable table_a = { &a_someCoolFunction, &a_anotherCoolFunction };
const struct functiontable table_b = { &b_someCoolFunction, &b_anotherCoolFunction };
const struct functiontable *ftable = NULL;
To switch the active function table, you'd use:
ftable = &table_a;
To call the functions, you'd use:
ftable->someCoolFunction();

Related

How to create a variable that will contain pointer to function regardless of arguments?

I want to make Dialog handler for my app that will contain pointer to method that will be invoked when user answer "yes" and pointer to method for "no" and the main problem that these methods can have various args or without it so i dont know how to declare this variable.
class Dialog
{
protected:
Dialog()
{
}
static Dialog* singleton;
public:
Dialog(Dialog &other) = delete;
void operator=(const Dialog &) = delete;
static Dialog *instance();
string question;
?? method_yes;
?? method_no;
static bool has_dialog();
static void clear();
};
Dialog* Dialog::singleton = nullptr;
Dialog* Dialog::instance()
{
if (singleton == nullptr) {
singleton = new Dialog();
}
return singleton;
}
bool Dialog::has_dialog()
{
return singleton != nullptr;
}
void Dialog::clear()
{
if (singleton)
{
delete singleton;
singleton = nullptr;
}
}
So there is my class for dialog with user, when i want to ask user something i do
auto yes = []()
{
ExitProcess(0);
};
Dialog::instance()->question = "Do you want to exit?";
Dialog::instance()->method_yes = yes;
And somewhere upper or whatever i have answer handling
if (Dialog::has_dialog())
// render question and buttons
// if pressed button yes
Dialog::instance()->method_yes();
Dialog::clear();
And what if for example i want to manage exit code so my lambda will be
auto yes = [](int code)
{
ExitProcess(code);
};
But then there is a new argument so i cant just use
void(*method_yes)();
for declaration
At the end of the day, C++ is a strongly typed language and you'll have to provide the set of expected possible arguments in your function signature.
Since you don't want that, there are some techniques to circumvent it so let's name a few:
The old (old old) void* trick from C. You declare your function pointer as
void (*fptr)(void* state);
and then you're free to interpret state however you wish in your fptr, e.g. if state==nullptr you can assume there are "no arguments". Note that this approach is not type safe and can cause a lot of headaches if users don't respect the agreed upon protocol.
You bundle all your state in your callable and your function pointer becomes something like std::function<void()>. This way you can write:
std::function<void()> fptr = [code]() { /* ... */ };
This is the nerfed version of the above, meaning your lambdas are now responsible for capturing the state you'd be passing to the function as arguments.
A pattern I'm using lately involves C++20 designated initializers like so:
struct Argument
{
std::optional<int> code;
std::optional<std::string> name;
std::optional<float> value;
};
void (*fptr)(Argument arg); // Argument is elastic, i.e.
// it can be formed as:
// {} -> no arguments
// {.code=1} -> 1 argument
// {.code=1, value=2.}-> 2 arguments
// etc
// Fields not mentioned default to
// nullopt, which means you have
// an easy way of telling them apart
int main ()
{
fptr = [](Argument arg) {
std::cout << arg.code.value_or(0) << std::endl;
std::cout << arg.name.value_or("no name") << std::endl;
std::cout << arg.value.value_or(42) << std::endl;
};
fptr({});
std::cout << "-------------\n";
fptr({.name="Garfield"});
std::cout << "-------------\n";
fptr({.code=3, .value=3.14});
std::cout << "-------------\n";
}
This is a type-safe alternative to (1). You declare the expected set of arguments in Argument but since they are optional you can call fptr({}) and mark everything as "non existent" (the no args case) or even initialize one or more arguments explicitly e.g. fptr({.code=3, .value=3.14}). Inside fptr you can inspect whether an optional variable is "filled" and this gives you the freedom to act accordingly (demo).
If all this still seems unattractive, I wrote a post some years ago on how to create overload sets out of lambdas. Essentially the technique allows you to write things like:
auto fptr = overload(
[]{ /*...*/ }, // A
[](int code) { /*...*/ }); // B
fptr(); // Calls A
fptr(22); // Calls B
Again this means that all possible solutions (sets of functions of different types) are known at compile time, but you dodge the pain of creating that set explicitly.
Finally I'd re-visit the design before resorting to such solutions, maybe a simpler path exists e.g. express the exit functions as a hierarchy and have a factory method to generate the active function at runtime or even reconsider why should an exit function be tweakable at runtime.

Can I use std::bind to convert a pointer to member function into a pointer to function?

I want to pass a member function as a call-back. The call back is a basic function pointer.
So I have something like:
h file:
void (*pRequestFunc) (int someint) = 0;
void RegisterRequestCallBack(void (*requestFunc) (int someint))
{
pRequestFunc = requestFunc;
}
class A
{
void callBack(int someint);
}
Cpp File:
RegisterRequestCallBack(&A::callBack); // This does not work.
Note I have tried to extract this example from my larger example and cut out all the other stuff - so it might not be perfect.
The problem, as far as I understand, is that member function pointers really (under the hood) have an extra parameter (and instance - i.e. this) and are not compatible with normal function pointers.
the RegisterRequestCallBack() is in reality not my code - and so I can't change that.
So I read that boost::bind can do what I need - and I am hoping c++11 std::bind can do the same - but I could not figure out how to use it to effectively get a standard function pointer from a member function pointer...
I was going for something like:
std::bind(&A::callBack) ... that is about as far as I got, my understanding of the examples online is poor :(
NathanOliver's comment is correct, and your suspicion is mostly correct. Exactly how pointers to member functions work is not specified, but including this as a hidden argument mostly works. You just need a bit of extra work for inheritance and pointers to virtual functions (yes, you can take their address too).
Now, often callbacks include a void* parameter under your control, which you can use to pass a A*. In those cases, you can write a wrapper (static) function that casts the void* back to A* and does the actual call to &A::callback.
That's not the case here. Registration takes a single function, without data. To get this to work in real-life situations, you have to resort to drastic solutions - not portable C++. One such method is to dynamically generate assembly (!). You create - at runtime - the compiled equivalent of
void __trampoline_0x018810000 (int i)
{
A* __this = reinterpret_cast<A*>(0x018810000);
__this->callback(i);
}
As you can see, you have to generate one trampoline for every A* value, and managing lifetimes of these is a major pain.
To be able to bind to a member function you need to do:
std::function<void(int)> function = std::bind(&A::foo, this, std::placeholders::_1);
Or in your case:
RegisterRequestCallBack(std::bind(&A::callback, this, std::placeholders::_1));
But in my opinion the clearest way to achieve this is to use lambda functions. Here you have an example to for doing something similar that could inspire you:
#include <array>
#include <map>
#include <vector>
#include <functional>
#include <iostream>
class TaskManager {
public:
using task_t = std::function<void()>;
void run();
void addTask(task_t task);
private:
std::vector<task_t> _tasks;
};
void TaskManager::run() {
for (auto& task : _tasks) {
task();
}
}
void TaskManager::addTask(task_t task) {
_tasks.push_back(task);
}
class Example {
public:
Example(){
taskManager.addTask([this]() {
task1();
});
taskManager.addTask([this,a=int(4)](){
task2(a);
});
}
TaskManager taskManager;
private:
void task1(){ std::cout << "task1!\n"; }
void task2(int a){ std::cout << "task2 says: " << a << "\n"; }
};
int main() {
Example example;
example.taskManager.run();
}
which outputs:
task1!
task2 says: 4

Binding member function to a local static variable

Precondition:
Here is a function:
typedef std::function<void (int)> Handler;
void g(const Handler& h) {
h(100);
}
, and a class:
class A {
public:
void f0(int n) {
std::cout << m + n << std::endl;
}
void f1() {
::g(std::bind(&A::f0, this, std::placeholders::_1));
}
int m;
};
And this will print two lines, '101' and '102':
int main() {
A a1;
a1.m = 1;
a1.f1();
A a2;
a2.m = 2;
a2.f1();
return 0;
}
Now I realized A::f1() will be called very frequently,
so I modified it like this(new version):
void A::f1() {
static const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
My Questions:
Is it safe to bind this pointer to a local static variable?
Is there no functional difference between two versions?
Can I expect the new version will really gain some performance benefit?
(I suspect my compiler(MSVC) will optimize it by itself,
so I may not need to optimize it by myself).
EDITED ----------
I run the new version and realized that the result is not the same as the original one.
It prints two lines, '101' and '101' again(not '102').
Poor question, sorry for all.
EDITED 2 ----------
Please refer to my new question which I might truly intend:
Binding member function to a member variable
No, this is not safe (nor works as intended). The static variable is shared among all instances to A, and you bind this in this static function object kHandler when calling f1 for the first time. So the bound parameter is always equal to the instance on which you called f1 first, i.e. in your case a1.
It's basically the same with this function:
int f(int a) {
static int b = a;
return b;
}
Call this function multiple times, and you will always get the value of the first call. (Demo)
Alternatives:
You could, if you can live with a space overhead, use a member variable for the bound function, though. I guess implementing this is straight-forward.
A non-thread-safe alternative (I'd not recommend using this!) could be to store the "this" pointer in a static member variable ("that") and make f0 static and use "that" instead of "this":
class A {
static A * that = nullptr;
public:
static void f0(int n) {
assert(that);
std::cout << that->m + n << std::endl;
}
void f1() {
assert(!that);
that = this;
::g(&A::f0);
that = nullptr;
}
int m;
};
Raymond Chen's comment is Correct - by using static you're only ever creating one instance of kHandler, and if the instance of A associated with that first call ever dies, then the bound "this" pointer will be dead.
I recommend removing static:
void A::f1() {
const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
This is safe because kHandler will exist across the lifetime of the g call.

generic non-invasive cache wrapper

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?

C++ Function List

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