Shown below is a working code. But I want to use "this" keyword to call my function pointers inside my implementation (e.g inside the constructor implementation). Please help me to come up with a solution.
My system is
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55)
Working Code
#include <iostream>
#include <string>
#include <map>
using namespace std;
class TestClass{
public:
typedef int (TestClass::*FunctionPtr)(int);
map <string, FunctionPtr> mFnPtrMap;
int Function1( int nAdd ) { return nAdd + 1; }
int Function2( int nAdd ) { return nAdd + 2; }
TestClass() {
mFnPtrMap.insert( make_pair( "Function1", &TestClass::Function1) );
mFnPtrMap.insert( make_pair( "Function2", &TestClass::Function2) );
}
int CallFunction( const string & s, int n ) {
FunctionPtr fp = mFnPtrMap[s];
return (this->*fp)(n);
}
};
int main() {
TestClass ts;
cout << ts.CallFunction( "Function1", 0 ) << endl;
cout << ts.CallFunction( "Function2", 0 ) << endl;
}
What I want to do is:
My expectation is to change it into something like this (use 'this->' instead of 'TestClass::')
mFnPtrMap.insert( make_pair( "Function1", &this->Function1) );
It gives me a compiler error. It even suggests me to use TestClass:: name resolution.
"ISO C++ forbids taking the address of a bound member function to form
a pointer to member function. Say &TestClass::Function1"
Does that mean it's not possible? If someone could give me an explanation also, it would help me to understand the theory underneath. Thank you.
If I had to guess for a reason behind this part of the C++ standard, it's that the types of expressions are hardly equivalent. Just compare how you would need to call the function if in a single expression without the function call as some sort of indirection:
(this->*TestClass::function)(); // Binding the member pointer to an instance
Here we bind the member pointer to an instance with the ->* operator which fills the implicit T* argument each member function has, the one named this. Some other language ask you to provide it explicitely, for example Python but I'm sidetracking a bit.
this->function();
Here the subexpression this->function already bound the parameter of this to the local this object which mean that this does in fact in no way refer to a function. Consequently, you can not take an address of it.
You could argue that this should be allowed as part of the standard but consider the fact that you can shadow function declarations in child classes. That means that introducing a second expression for expressing &TestClass::function would only introduce confusion. In the current form it is very clear which function we are referring to whereas in a this->function form it would not be, especially newcomers might assume that this is completely dynamic as this is not a static object. It would also not be interely unreasonable to assume that there in fact is a difference between the expressions.
In the mean time, I can only offer a way to remove the explicit referal to the class by some type level computations:
#include <type_traits>
template<typename T>
using This = typename std::remove_const<typename std::remove_pointer<T>::type>::type;
TestClass::TestClass() {
mFnPtrMap.insert( make_pair( "Function1", &This<decltype(this)>::Function1) );
mFnPtrMap.insert( make_pair( "Function2", &This<decltype(this)>::Function2) );
}
Related
I'm trying to create a std::discrete_distribution object using data passed into a class constructor. I know how to create this using static data, but cannot figure out how using variable data (cleanly). What I have now "works", but is painful. Is there a more appropriate way of doing this?
The distInit = { distArray[0], ... }; line is the problem.
#include <iostream>
#include <iomanip>
#include <initializer_list>
#include <map>
#include <random>
class Die {
private:
int loadSide;
double loadAmount;
std::mt19937 generator;
std::discrete_distribution<> distribution;
std::initializer_list<double> distInit;
std::array<double, 7> distArray;
public:
Die( int loadSide, double loadAmount ) : loadSide(loadSide), loadAmount(loadAmount) {
distArray.fill( 1 );
distArray[0] = 0;
distArray[this->loadSide] = this->loadAmount;
distInit = { distArray[0], distArray[1], distArray[2], distArray[3], distArray[4], distArray[5], distArray[6] };
distribution.param( distInit );
};
int roll( ) {
return distribution( generator );
};
};
const int ROUNDS = 10000;
int main() {
Die* die = new Die( 5, 20 );
std::map<int, int> m;
for(int n=0; n < ROUNDS; n++) {
m[die->roll()]++;
}
for(auto p : m) {
std::cout << p.first << " generated " << std::setiosflags(std::ios::fixed) << std::setprecision(2) << (float) p.second / ROUNDS << " times\n";
}
}
I may not be asking the right question, which I will apologize in advance for if so. This is a strong possibility as I'm surprised I'm unable to find any (apparently) related hits on this subject.
My compiler is g++-mp-4.8 (MacPorts gcc48 4.8-20130411_0) 4.8.1 20130411 (prerelease)
Command line /opt/local/bin/g++-mp-4.8 -std=c++11 test.cpp -o test
If you have variable data, you should be using the discrete_distribution constructor taking a pair of iterators:
template< class InputIt >
discrete_distribution( InputIt first, InputIt last );
You shouldn't be trying to construct the param_type directly; instead use a helper function to construct your distribution:
class Die {
private:
std::mt19937 generator;
std::discrete_distribution<> distribution;
static std::discrete_distribution<> makeDistribution(
int loadSide, double loadAmount )
{
std::array<double, 7> distArray;
distArray.fill( 1 );
distArray[0] = 0;
distArray[loadSide] = loadAmount;
return {std::begin(distArray), std::end(distArray)};
}
public:
Die( int loadSide, double loadAmount ) :
generator{ },
distribution{ makeDistribution( loadSide, loadAmount ) }
{}
int roll( ) {
return distribution( generator );
}
};
std::initializer_list only intended for use as a temporary object (function argument) or local variable. It's not a container and it doesn't own anything; it's an accessor to an anonymous, temporary array.
The Standard includes an example similar to your code, §8.5.4/6, which mentions
the initializer_list object is initialized in a constructor’s ctor-initializer, so the array persists only until the constructor exits, and so any use of the elements of i4 after the constructor exits produces undefined behavior.
In your case, it's the body of the constructor, not a ctor-initializer preceding the body, but the story is the same. It's just dumb luck that your program is working for now.
To store the distribution in the object, use std::array or std::vector. array is more efficient but it doesn't support arr = { … } syntax. (There are a few simple alternatives.) vector does support your syntax using braces and the = operator; this support uses an implicit std::initializer_list.
I don't know any better way to create a std::initializer_list from a container like std::array other than the one shown in the OP.
However, for the original problem, namely, passing the parameters to the distribution, I can suggest something simpler.
typedef std::discrete_distribution<>::param_type param_type;
distribution.param(param_type(distArray.begin(), distArray.end()));
The standard says that distributions must provide a type member param_type (which is the type of argument taken by param()) but doesn't specify it. However, [rand.req.dist] says that
For each of the constructors of D [the distribution type] taking arguments corresponding to parameters of the distribution, P [param_type] shall have a corresponding constructor subject to the same requirements and taking arguments identical
in number, type, and default values.
Well, it turns out that std::discrete_distribution<> has a constructor taking iterators pointing to the range of parameters. Therefore, whatever std::discrete_distribution<>::param_type is, it must have a similar constructor. Therefore, I'm suggesting creating a param_type from distArray.begin() and distArray.end() and pass it to distribution.param().
A side note: You no longer need std::initializer_list<double> distInit; in your class. It seems to me that you don't need std::array<double, 7> distArray as a class member either (it could be a local variable in Die's constructor).
I have 2 functions f() and g(). I want to call them in order every time. Can I get a boost::function to do this?
E.g. something like:
boost::function functor = boost::bind( boost::bind(f), boost::bind(g) );
Extend this further, say it takes arguments, then what I need is a chain of responsibility. Each node does something with arguments, then followed by next node of chain.
How do I do that?
Update Thanks for Seth Carnegie's comments.
I think what I really want is how to construct a chain of responsibility into a single boost::function, each node of chain can be constructed by using boost::bind().
Have you considered using boost::signal ?
With boost::signal you can connect multiple function calls into one.
#include <boost/signal.hpp>
#include <iostream>
void f()
{
std::cout << " Hello" << std::flush;
}
void g()
{
std::cout << " World" << std::endl;
}
int main()
{
boost::signal<void ()> s;
s.connect(f);
s.connect(g);
s();
}
Why not something like this?
#include <functional>
template <typename FirstFunctor, typename SecondFunctor>
void chainFunctionImpl(FirstFunctor first, SecondFunctor second)
{
first();
second();
}
template <typename FirstFunctor, typename SecondFunctor>
std::function<void(void)> chainFunction(FirstFunctor first, SecondFunctor second)
{
return std::bind(chainFunctionImpl<FirstFunctor,SecondFunctor>,first,second);
}
Use should be relatively simple, just binding the functions in sequence, then calling the result. Theoretically any length of functions could be chained up.
Note that is theoretically possible to do this with passing an argument down the chain as well, but that level of template foo is way beyond me. http://ideone.com/Xvp5U is where I gave up.
There is a quite easy solution using boost::lambda with its comma operator. In my case I am using it for a modificator function which is defined as (B is an arbitrary class for e.g. and A is a class which should be altered but resides in B and should not go outside)
void B::modify( boost::function<void(A&)> func );
My intention is to pass only the modificator to the modify function which makes it more easy to gain control when it is modified (for e.g. for emitting signals).
Sometimes I want to apply 2 modifier:
void A::setInvalid();
void A::setX( int x );
Calling in 2 steps which is not the way (just as reference to show how we want to use the modify method):
instanceA->modify(
boost::bind( &A::setInvalid, _1 );
instanceA->modify(
boost::bind( &A::setX, _1, 4 );
Using boost::lambda this can be joined to a single function call and therefore only one function is created:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
instanceA->modify(
( bind(&A::setInvalid, boost::lambda::_1)
, bind(&A::setX, boost::lambda::_1, 4) ) );
Related to your question this would look then:
using namespace boost::lambda;
boost::function<void()> func = ( bind(f), bind(g) )
I'm doing a linear genetic programming project, where programs are bred and evolved by means of natural evolution mechanisms. Their "DNA" is basically a container (I've used arrays and vectors successfully) which contain function pointers to a set of functions available.
Now, for simple problems, such as mathematical problems, I could use one type-defined function pointer which could point to functions that all return a double and all take as parameters two doubles.
Unfortunately this is not very practical. I need to be able to have a container which can have different sorts of function pointers, say a function pointer to a function which takes no arguments, or a function which takes one argument, or a function which returns something, etc (you get the idea)...
Is there any way to do this using any kind of container ?
Could I do that using a container which contains polymorphic classes, which in their turn have various kinds of function pointers?
I hope someone can direct me towards a solution because redesigning everything I've done so far is going to be painful.
A typical idea for virtual machines is to have a separate stack that is used for argument and return value passing.
Your functions can still all be of type void fn(void), but you do argument passing and returning manually.
You can do something like this:
class ArgumentStack {
public:
void push(double ret_val) { m_stack.push_back(ret_val); }
double pop() {
double arg = m_stack.back();
m_stack.pop_back();
return arg;
}
private:
std::vector<double> m_stack;
};
ArgumentStack stack;
...so a function could look like this:
// Multiplies two doubles on top of the stack.
void multiply() {
// Read arguments.
double a1 = stack.pop();
double a2 = stack.pop();
// Multiply!
double result = a1 * a2;
// Return the result by putting it on the stack.
stack.push(result);
}
This can be used in this way:
// Calculate 4 * 2.
stack.push(4);
stack.push(2);
multiply();
printf("2 * 4 = %f\n", stack.pop());
Do you follow?
You cannot put a polymorphic function in a class, since functions that take (or return) different things cannot be used in the same way (with the same interface), which is something required by polymorphism.
The idea of having a class providing a virtual function for any possible function type you need would work, but (without knowing anything about your problem!) its usage feels weird to me: what functions would a derived class override? Aren't your functions uncorrelated?
If your functions are uncorrelated (if there's no reason why you should group them as members of the same class, or if they would be static function since they don't need member variables) you should opt for something else... If you pick your functions at random you could just have several different containers, one for function type, and just pick a container at random, and then a function within it.
Could you make some examples of what your functions do?
What you mentioned itself can be implemented probably by a container of
std::function or discriminated union like Boost::variant.
For example:
#include <functional>
#include <cstdio>
#include <iostream>
struct F {
virtual ~F() {}
};
template< class Return, class Param = void >
struct Func : F {
std::function< Return( Param ) > f;
Func( std::function< Return( Param ) > const& f ) : f( f ) {}
Return operator()( Param const& x ) const { return f( x ); }
};
template< class Return >
struct Func< Return, void > : F {
std::function< Return() > f;
Func( std::function< Return() > const& f ) : f( f ) {}
Return operator()() const { return f(); }
};
static void f_void_void( void ) { puts("void"); }
static int f_int_int( int x ) { return x; }
int main()
{
F *f[] = {
new Func< void >( f_void_void ),
new Func< int, int >( f_int_int ),
};
for ( F **a = f, **e = f + 2; a != e; ++ a ) {
if ( auto p = dynamic_cast< Func< void >* >( *a ) ) {
(*p)();
}
else if ( auto p = dynamic_cast< Func< int, int >* >( *a ) ) {
std::cout<< (*p)( 1 ) <<'\n';
}
}
}
But I'm not sure this is really what you want...
What do you think about Alf P. Steinbach's comment?
This sort of thing is possible with a bit of work. First it's important to understand why something simpler is not possible: in C/C++, the exact mechanism by which arguments are passed to functions and how return values are obtained from the function depends on the types (and sizes) of the arguments. This is defined in the application binary interface (ABI) which is a set of conventions that allow C++ code compiled by different compilers to interoperate. The language also specifies a bunch of implicit type conversions that occur at the call site. So the short and simple answer is that in C/C++ the compiler cannot emit machine code for a call to a function whose signature is not known at compile time.
Now, you can of course implement something like Javascript or Python in C++, where all values (relevant to these functions) are typed dynamically. You can have a base "Value" class that can be an integer, float, string, tuples, lists, maps, etc. You could use std::variant, but in my opinion this is actually syntactically cumbersome and you're better of doing it yourself:
enum class Type {integer, real, str, tuple, map};
struct Value
{
// Returns the type of this value.
virtual Type type() const = 0;
// Put any generic interfaces you want to have across all Value types here.
};
struct Integer: Value
{
int value;
Type type() const override { return Type::integer; }
};
struct String: Value
{
std::string value;
Type type() const override { return Type::str; }
};
struct Tuple: Value
{
std::vector<Value*> value;
Type type() const override { return Type::tuple; };
}
// etc. for whatever types are interesting to you.
Now you can define a function as anything that takes a single Value* and returns a single Value*. Multiple input or output arguments can be passed in as a Tuple, or a Map:
using Function = Value* (*)(Value*);
All your function implementations will need to get the type and do something appropriate with the argument:
Value* increment(Value* x)
{
switch (x->type())
{
Type::integer:
return new Integer(((Integer*) x)->value + 1);
Type::real:
return new Real(((Real*) x)->value + 1.0);
default:
throw TypeError("expected an integer or real argument.")
}
}
increment is now compatible with the Function type and can be stored in mFuncs. You can now call a function of unknown type on arguments of unknown type and you will get an exception if the arguments don't match, or a result of some unknown type if the arguments are compatible.
Most probably you will want to store the function signature as something you can introspect, i.e. dynamically figure out the number and type of arguments that a Function takes. In this case you can make a base Function class with the necessary introspection functions and provide it an operator () to make it look something like calling a regular function. Then you would derive and implement Function as needed.
This is a sketch, but hopefully contains enough pointers to show the way. There are also more type-safe ways to write this code (I like C-style casts when I've already checked the type, but some people might insist you should use dynamic_cast instead), but I figured that is not the point of this question. You will also have to figure out how Value* objects lifetime is managed and that is an entirely different discussion.
I have the following code which works as expected:
#include <iostream>
using namespace std;
typedef int (TMyFunc)(int);
TMyFunc* p;
int x(int y)
{
return y*2;
}
int main()
{
p = &x;
cout << (*p)(5) << endl;
}
What I want to do is skip defining x and define p there straight. Something like
TMyFunc p; p(y){return y*2;}.
Is that possible? If so how do I do it? If not why?
EDIT:
After seeing the answers, I think I should clarify: I want the definition to be separate. i.e. function definition will be in a shared object. An application will acquire a function pointer to the function via dlsym. I do not want a function object. What I want is to know if I can define a function using its type which a header file common to both the shared object and the application will provide. I hope that came out right :).
EDIT2: For sbi :)
This resides in a header which is included in both the application and the shared object:
#define FNAME_GET_FACTORY "GetFactory"
#define FNAME_GET_FUNCTION_IDS "GetFunctionIDs"
#define FNAME_GET_PLUGIN_INFO "GetPluginInfo"
typedef FunctionFactory* (*TpfGetFactory)();
typedef size_t (*TpfGetFunctionIDs)(int**);
typedef PluginInfo* (*TpfGetPluginInfo)();
In the application, something like this happens:
TpfGetFactory pF = (TpfGetFactory)dlsym(pHandle, FNAME_GET_FACTORY);
//Use pF for anything
Now, to do this, I have to define GetFactory as follows in the shared object:
extern "C" FunctionFactory* FNAME_GET_FACTORY(){//CODE}
Forgetting the extern "C" part for now, Can I define this function using the type TpfGetFactory which is already defined? (This is not a huge issue I know - but I am curious as to whether it is possible :) ). What I want is something like this in the shared object :
TpfGetFactory f;
f(){//Implementation}
EDIT3:
My try:
#include <iostream>
using namespace std;
typedef int (TF)(int);
TF f;
f(int x)
{
return x*2;
}
int main()
{
x(3);
}
main.cpp:9: error: ISO C++ forbids declaration of ‘f’ with no type
main.cpp: In function ‘int main()’:
main.cpp:16: error: ‘x’ was not declared in this scope
It's possible in C++1x, the next C++ standard, generally expected next year (which would make it C++11, then). It allows this:
auto p = [](int y){return y*2;};
This relies on auto been given a new meaning ("automatically deduce the type of this variable from the expression that initializes it") and the new lambda functions (allowing to create functions on the fly).
Your compiler might actually already support this.
This works fine for me, with the current C++03 Standard:
typedef int (TMyFunc)(int);
TMyFunc* p;
int test()
{
struct LocalClass
{
static int functionLocal(int y)
{
return 2;
};
};
LocalClass localClass;
p = &(LocalClass::functionLocal);
}
But maybe it happens to be more complicated to write than what you wanted to simplify ;-),
however it works and you can define your functions in place, locally.
Here is some documentation about local classes
This will be possible in the next C++ standard, via lambdas. In the current standard, however, it is impossible to define one function inside another.
Not directly in C++98.
For standard C++, that is C++98, check out e.g. the Boost Lambda library. It lets you write expressions like
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
C++0x adds direct support for lambda expressions.
Cheers & hth.,
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?