Dear Stack Exchange Experts,
I am trying to set up a class (multivariate distribution function) that stores boost distributions in a std::vector (marginal distribution functions).
While this is possible using boost::variant (see my question: Boost: Store Pointers to Distributions in Vector), I also gave boost::any a try.
The reason being that with variant I have to hard-code the potential types (marginal distributions) when setting up the variant and I wanted to avoid this.
While the different implemented distribution classes do not share a common parent class, there are functions such as boost::math::cdf or boost::math::pdf that can be applied to all distributions, and that I want to apply iterating over the std::vector.
Working with any I produced the code below (which is running fine), but now I have the problem that the function any_cdf needs to check the types.
While I circumvented hard-coding the types when setting up the vector (as for variant) I now need to hard-code the types in the any_cdf function (while the solution with variants can handle the application of the cdf function via a templated visitor function, and thus without any type specifications) which means lots of code to manage, lots of if statements...
However, the logic does not change at all (I cast the type, then apply the cdf function in all if statements), and I wouldn't really care how the function behaves if something other than a boost distribution gets stored in the list.
So is there any chance to have my cake and eat it, meaning not being forced to hard-code the casting type of the distribution in any_cdf (much like a templated visitor function for variants)?
Thanks so much for your help, H.
P.s. if this is not feasible, would I generally be better of with boost::any or boost::variant in this situation?
#include <boost/math/distributions.hpp>
#include <boost/any.hpp>
#include <vector>
#include <iostream>
#include <limits>
//template function to apply cdf
template<class T> T any_cdf(boost::any a, T &x){
//declare return value
T y;
//cast any with hardcoded types
if (a.type() == typeid(boost::math::normal_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::normal_distribution<T> >(a),x);
} else if (a.type() == typeid(boost::math::students_t_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::students_t_distribution<T> >(a), x);
} else {
//return NaN in case of failure or do something else (throw exception...)
y = std::numeric_limits<T>::quiet_NaN();
}
return(y);
}
int main (int, char*[])
{
//get distribution objects
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
//use any to put just any kind of objects in one vector
std::vector<boost::any> vec_any;
vec_any.push_back(s);
vec_any.push_back(t);
//evaluation point and return value
double y;
double x = 1.96;
for (std::vector<boost::any>::const_iterator iter = vec_any.begin(); iter != vec_any.end(); ++iter){
y = any_cdf<double>(*iter,x);
std::cout << y << std::endl;
}
return 0;
}
Edit: Concerning the comments any seems not to be the easiest/best choice for the task at hand. However for completeness reasons a visitor like implementation for boost::any is discussed at:
visitor pattern for boost::any
Note See my older answer for a discussion of solutions a vector and boost::any vs. boost::variant.
If you don't actually need a dynamic vector of distributions - but just want to apply a statically known list of distributions, you can "get away" with a tuple<> of them.
Now, with a bit (well, a lot) of magic from Phoenix and Fusion, you can "just" adapt the cdf function as a Lazy Actor:
BOOST_PHOENIX_ADAPT_FUNCTION(double, cdf_, boost::math::cdf, 2)
In which case an equivalent extended code sample shrinks to: See it Live On Coliru
int main()
{
typedef boost::tuple<bm::normal, bm::students_t> Dists;
Dists dists(bm::normal(), bm::students_t(1));
double x = 1.96;
boost::fusion::for_each(dists, std::cout << cdf_(arg1, x) << "\n");
std::cout << "\nComposite (multiplication):\t" << boost::fusion::accumulate(dists, 1.0, arg1 * cdf_(arg2, x));
std::cout << "\nComposite (mean):\t\t" << boost::fusion::accumulate(dists, 0.0, arg1 + cdf_(arg2, x)) / boost::tuples::length<Dists>::value;
}
Whoah. That's... hardly 6 lines of code :) And the best part is it's all c++03 compatible already.
Update This is the answer assuming a vector and boost::any vs. boost::variant. If you can use a tuple<> see my other answer
You will end up hardcoding the potential types one way or another.
With variant, you can group and hide the complexities by using visitor:
struct invoke_member_foo : boost::static_visitor<double>
{
template <typename Obj, typename... Args>
double operator()(Obj o, Args const&... a) const {
return o.foo(a...);
}
};
This can be applied to your variant like
boost::apply_visitor(invoke_member_foo(), my_variant);
With boost any, you'd do the typeswitching the boring and manual way:
if (auto dist1 = boost::any_cast<distribution1_t>(&my_any))
dist1->foo();
else if (auto dist2 = boost::any_cast<distribution2_t>(&my_any))
dist2->foo();
else if (auto dist3 = boost::any_cast<distribution3_t>(&my_any))
dist3->foo();
IMO this is clearly inferior for maintainability e.g.
you can't easily extend the type list with an element type that is similar enough to satisfy the same concept and have it support - you'll need to add cases to the type-switch manually (and if you don't - you're out of luck, there is no error and you'll have (silent) bugs. With variant you'll just get a compile error whenever your visitor doesn't handle your type.
this work ^ (the type switching) gets duplicated for each operation that you want to implement across the board. Of course, you can implement the type-switch once, and provide the actual implementation as a functor, but at that moment you'll have implemented the exact equivalent of a static_visitor as I showed for the variant, except with far less efficient implementation.
boost::any can only contain values that are CopyConstructible. Boost variant can even contain references (e.g. boost::variant<dist1_t&, dist2_t&>) and has (some) move-semantics support
In short, boost::any saves on time thought in advance, but all it does is shift the work to the call-sites.
On a positive note, let me share with you an idiom I like, which makes visitors accessible as ordinary free functions. Let's rewrite your any_cdf function for the variant:
namespace detail
{
template <typename T> struct var_cdf_visitor : boost::static_visitor<T> {
template <typename Dist>
T operator()(Dist& dist, T& x) const { return boost::math::cdf(dist, x); }
};
}
template<class T> T var_cdf(VarDist<T> a, T &x)
{
static detail::var_cdf_visitor<T> vis;
return boost::apply_visitor(
boost::bind(vis, ::_1, boost::ref(x)),
a);
}
A full running program can be found Live On Coliru
Demo Listing
#include <boost/bind.hpp>
#include <boost/math/distributions.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <limits>
#include <vector>
namespace detail
{
template <typename T> struct var_cdf_visitor : boost::static_visitor<T> {
template <typename Dist>
T operator()(Dist const& dist, T const& x) const { return boost::math::cdf(dist, x); }
};
}
template<class T, typename... Dist> T var_cdf(boost::variant<Dist...> const& a, T const& x) {
return boost::apply_visitor(boost::bind(detail::var_cdf_visitor<T>(), ::_1, x), a);
}
int main()
{
namespace bm = boost::math;
typedef std::vector<boost::variant<bm::normal, bm::students_t> > Vec;
Vec vec { bm::normal(), bm::students_t(1) };
//evaluation point and return value
double x = 1.96;
for (auto& dist : vec)
std::cout << var_cdf(dist,x) << std::endl;
}
Actually, though I used a bit of c++11, this could be made even prettier using some c++1y features (if your compiler has them).
And lastly, you can make work for c++03 too; it would just require more time than I currently have to throw at it.
What about:
int main (int, char*[])
{
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
typedef std::vector<boost::function<double (double)> > vec_t;
vec_t vec_func;
vec_func.push_back(boost::bind(boost::math::cdf<double>, boost::ref(s), _1));
vec_func.push_back(boost::bind(boost::math::cdf<double>, boost::ref(t), _1));
//evaluation point and return value
double y;
double x = 1.96;
for (vec_t::const_iterator iter = vec_func.begin(); iter != vec_func.end(); ++iter){
y = (*iter)(x);
std::cout << y << std::endl;
}
return 0;
}
Binding argument to a function template can be tricky though.
Related
The ultimate goal of this is to have a function which can take a variable number of arguments of a certain type (the same type, not different types), that can be declared on the function call.
As I'm using Visual Studio 2010, I CANNOT do:
MyFunction({1,2,3});
In an earlier question which was answered, I found I could use boost::assign::list_of(), however I discovered later that this seems to have a bug of some kind if you try to pass it only one parameter.
So I did some more searching and found that I could use variadic functions to achieve what I was aiming for.
void TestFunction2<int>(int count, ...)
{}
However, I wanted to restrict it by type, so eventually found I could do this with templates:
template <class T>
void TestFunction(const T& count, ...);
template <>
void TestFunction<int>(const int& count, ...);
Unfortunately, varargs things like va_list do not apparently like references. The examples I saw to restrict types like this used const references. If I remove the const reference aspect of the count parameter, it works as I want, but I don't know if this is going to lead to horrible side-effects down the road, OR if this whole varargs thing is a bad idea to begin with.
So I guess my question is, is what I'm doing in the last example above good or bad? If it's bad, what is a good alternative so I can call a function with one or more parameters in-line like, say, int parameters?
What you want is std::initializer_list<T>, unfortunately this require C++11 support.
An alternative, that is nearly as elegant and easy enough to upgrade from, is to use an array:
#include <iostream>
template <typename T, size_t N>
void func(T (&s)[N]) {
for (size_t i = 0; i != N; ++i) {
std::cout << s[i] << '\n';
}
}
int main() {
int array[] = {1, 2, 3};
func(array);
}
When you move on to a compiler that supports initializer lists, this can be changed into:
#include <iostream>
template <typename T>
void func(std::initializer_list<T> s) {
for (T const& t: s) {
std::cout << t << '\n';
}
}
int main() {
func({1, 2, 3});
}
So both the function and call sites update will be painless.
Note: the call site could be made completely similar using a macro, I advise against such approach, the purported gain is not worth the obfuscation.
EDIT:
One more solution... if your compiler's IDE partially supports C++11, you may be able to initialize a std::vector at call time, i.e.
template <typename T>
void TestFunction(std::vector<T> vect)
{
....
}
....
TestFunction(std::vector<int>{1,2,3});
Advantages to this approach are that STL automatically frees the allocated memory when the function goes out of scope.
If that doesn't work you can resort to a two liner...
template <typename T>
void TestFunction(std::vector<T> vect)
{
....
}
....
std::vector<int> tmp(1,2,3);
TestFunction(tmp);
The big downside is that here the memory sits on stack until you leave that scope (or explicitly resize the vector to zero length.
Both approaches share some advantages... the count is built in and you have access to other useful member functions or affiliate methods (like std::sort).
......................................
Why not use variable arguments?
See the answer here, for example...
Is it a good idea to use varargs in a C API to set key value pairs?
On non-C+11 compliant compilers (like your IDE), you can try...
template <typename T>
TestFunction(const unsigned int count, T * arr)
TestFunction<std::string>(10, new string[] {"One", "Two", "Three"});
(Sounds like you can't use this in your IDE, but...)
If you're confident you're only compiling on modern machines and are primarily using simple types, this is best/most standards compliant solution...
As of C++11 you can use std::initializer which is in std::vector:
#include<vector>
template <typename T>
void TestFunction(const std::initializer_list<T>& v)
{ }
int main()
{
TestFunction<double>({1.0, 2.0});
return 0;
}
..........................
...however this requires your compiler to be C+11 so it's not perfectly portable. For anything other than simple types, it also becomes harder to read.
I realize you say on the function call, but you may want to rethink that from a readability and ease of coding approach.
I agree with part of your approach -- what you want is to use a template function (this handles the variable type). Before you call you initialize your collection of same-type elements into a temporary standard C array or a std::vector/std::list (STL's array wrapper).
http://www.cplusplus.com/doc/tutorial/templates/
http://www.cplusplus.com/reference/vector/
http://www.cplusplus.com/reference/list/
It's more lines of code, but it's much more readable and standardized.
i.e.
Rather than...
MyFunction({1,2,3});
Use:
template <typename T>
void TestFunction(const int count, T * arr)
{
for (unsigned int i = 0; i < count; i++)
{
.... arr[i] ... ; //do stuff
...
}
}
int main()
{
int * myArr = {1,2,3};
TestFuntion<int>(3, myArr);
}
...or...
#include <vector>
template <typename T>
void TestFunction(std::vector<T> vect)
{
for (unsigned int i = 0; i < vect.size(); i++)
{
.... vect[i] ... ; //do stuff
...
}
}
int main()
{
std::vector<int> myVect;
myVect.push_back(1);
myVect.push_back(2);
myVect.push_back(3);
TestFuntion<int>(myVect);
}
std::list would also be a perfectly acceptable, and may perform better, depending on your use case.
What are the benefits of using boost::any_range?
Here is an example:
typedef boost::any_range<
int
, boost::forward_traversal_tag
, int
, std::ptrdiff_t
> integer_range;
void display_integers(const integer_range& rng)
{
boost::copy(rng,
std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
}
int main(){
std::vector<int> input{ ... };
std::list<int> input2{ ... };
display_integers(input);
display_integers(input2);
}
But the same functionality with more efficiency can be achieved with a template parameter, which satisfies the ForwardRange concept:
template <class ForwardRange>
void display_integers(const ForwardRange& rng)
{
boost::copy(rng,
std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
}
So I am searching for scenarios when it is worth to use any_range. Maybe I am missing something.
This technique is called Type Erasure. There is a full article describing the pros and cons on the example of any_iterator: On the Tension Between Object-Oriented and Generic Programming in C++.
It is possible to hide (in a separate file/library) the implementation/definition of
void display_integers(const integer_range& rng)
But in the case of
template <class ForwardRange>
void display_integers(const ForwardRange& rng)
you have to provide source code to users (or at least make explicit instantiations somewhere).
Moreover, in the first case, display_integers will be compiled only once, but in the second it will be compiled for every type of the passed range.
Also, you may have somewhere
integer_range rng;
and during lifetime of rng you may assign ranges of different types to it:
vector<int> v;
list<int> l;
integer_range rng;
rng = v;
rng = l;
The biggest disadvantage of type erasure is its runtime cost; all operations are virtual, and cannot be inlined (easily).
P.S. another famous example of type erasure is std::function
boost::any_range can used for returning ranges from functions. Imagine the following example:
auto make_range(std::vector<int> v) -> decltype(???)
{
return v | filter([](int x){ return x % 2 == 0;})
| transform([](int x){ return x * 2;});
}
*: gcc does not compile the above without wrapping it in std::function, hower clang 3.2 works by directly passing the lambda
It is very difficult to know what is being returned from this function. Also, lambda and decltype don't work together so we cannot deduce the type using decltype when passing only a lambda. One solution is to use boost::any_range like the one in your example (another workaround is to use std::function as pointed out by Evgeny Panasyuk in the comments):
integer_range make_range(std::vector<int> v)
{
return v | filter([](int x){ return x % 2 == 0;})
| transform([](int x){ return x * 2;});
}
Working example with gcc using std::function.
Working example with clang passing lambdas directly.
This question already has answers here:
Is there a way to pass auto as an argument in C++?
(4 answers)
auto parameter type in functions
(1 answer)
Closed 4 months ago.
Is it possible to create a generic C++ function foo?
foo(Object bar, Object fred)
{
//code
}
in which that if the two objects are recognized, they are compared and a comparison value is returned otherwise some other value is returned to indicate a comparison was not possible?
I ask in the case of genericizing a sorting class, in which case you can use this method, and when you derive new objects you want to sort, you add to this foo function, a method on which to sort the new type of Object.
Using templates, define two versions of the function, one where the parameters are the same type and one where they can be different:
#include <string>
#include <iostream>
using namespace std;
template<typename Type>
void func(Type, Type)
{
cout << "same" << endl;
}
template<typename TypeA, typename TypeO>
void func(TypeA, TypeO)
{
cout << "different" << endl;
}
int main()
{
func(5, 3); // same
func(5, 3.0); // different
func(string("hello"), "hello"); // different
func(5.0, 3.0); // same
return 0;
}
Output:
same
different
different
same
I think you are in dire need of Templates!
You can write a template function and then write a specialization for the said types to do something specific if the need be.
template<class Type1, class Type2>
void foo(Type1 t1, Type2 t2)
{
// put code here for function
}
call as
foo<std::string, int> ("hello", 10);
Most probably you need to use templates as other people suggest:
template <class T>
return_type func(T const& l, T const& r)
{
...
}
Because you normally want compilation to fail when the operation implemented by a generic function does not make sense for particular types, so you would either use conditional definition (in the below example is_arithmetic):
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
template <class T>
typename boost::enable_if<boost::is_arithmetic<T>, return_type>::type
func(T const& l, T const& r)
{
...
}
or static assertion in the code to yield the same result:
#include <boost/type_traits/is_arithmetic.hpp>
template <class T>
return_type func(T const& l, T const& r)
{
static_assert(boost::is_arithmetic<T>::type::value, "incompatible types");
...
}
I'm going to stick my neck out here and say you don't need Templates to do this. I'm not saying don't use them, but just that depending on exactly what you're wanting to do, there are alternatives.
What it sounds like you want is the ability to compare two generic objects provided that they adhere to a common set of ground rules. You could actually implement this using traditional inheritance or using templates. The choice of which you want comes down to how flexible you need it to be and whether you want some of the decisions to be made at runtime or compile time. If the latter - i.e. you want to pick up on casting errors etc., - then go for templates.
Either way, your objects will either have to adhere to some basic groundrules for how you compare them and preferably encapsulate that - this way your comparitor would be generic. or you'd have to write different comparitors for each object comparison. While it sounds like the latter is what you want, be wary of letting too much of your class implementation leach out into the comparitor function and thereby breaking encapsulation.
From my own experience, going straight to the template approach can occasionally result in a lot of bloated, messed up code which is hard to read, debug and maintain. Take a hard look at you design and what you actually need first.
OP seems to want to know if the 2 objects are comparable or not. You can use template specialization to achieve this (note: this doesn't compile on VC 10, but does on g++ 4.7). The only nuance, is you want this function to
they are compared and a comparison value is returned otherwise some other value is returned to indicate a comparison was not possible
But you need to define some sort of structure to signify that a comparison was not possible; using a magic number '-500' or whatever is not good style. Alternately, you could throw an error, and allow it to be caught an handled.
struct NoCompare{};
template <typename U1, typename U2>
static auto compare2(const U1 & u1, const U2 & u2) -> decltype(u1 == u2)
{
cout << "Comparable" << endl;
return u1 == u2;
}
static int compare2(...)
{
// Comparison not supported - return whatever value you want. (change the return type as appropriate)
cout << "Not comparable" << endl;
return -500;
}
int main()
{
int a = 5, b = 3, c = 3;
NoCompare dns;
cout << compare2(a, b) << endl;
cout << compare2(dns, b) << endl;
cout << compare2(c, b) << endl;
return 0;
}
Output:
C:\MinGW\MinGW>a
Comparable
0
Not comparable
-500
Comparable
1
It seems that you are referring to Common Lisp / CLOS -style generic functions which do multiple dynamic dispatch. C++ does single dynamic dispatch with methods but only single static dispatch with functions. So the answer is no. C++ doesn't support this at the moment. There have been proposals along the years to add it into the language but that hasn't happened yet.
Here's the code. Is it possible to make last line work?
#include<iostream>
using namespace std;
template <int X, int Y>
class Matrix
{
int matrix[X][Y];
int x,y;
public:
Matrix() : x(X), y(Y) {}
void print() { cout << "x: " << x << " y: " << y << endl; }
};
template < int a, int b, int c>
Matrix<a,c> Multiply (Matrix<a,b>, Matrix<b,c>)
{
Matrix<a,c> tmp;
return tmp;
}
int main()
{
Matrix<2,3> One;
One.print();
Matrix<3,5> Two;
(Multiply(One,Two)).print(); // this works perfect
Matrix Three=Multiply(One,Two); // !! THIS DOESNT WORK
return 0;
}
In C++11 you can use auto to do that:
auto Three=Multiply(One,Two);
In current C++ you cannot do this.
One way to avoid having to spell out the type's name is to move the code dealing with Three into a function template:
template< int a, int b >
void do_something_with_it(const Matrix<a,b>& One, const Matrix<a,b>& Two)
{
Matrix<a,b> Three = Multiply(One,Two);
// ...
}
int main()
{
Matrix<2,3> One;
One.print();
Matrix<3,5> Two;
do_something_with_it(One,Two);
return 0;
}
Edit: A few more notes to your code.
Be careful with using namespace std;, it can lead to very nasty surprises.
Unless you plan to have matrices with negative dimensions, using unsigned int or, even more appropriate, std::size_t would be better for the template arguments.
You shouldn't pass matrices per copy. Pass per const reference instead.
Multiply() could be spelled operator*, which would allow Matrix<2,3> Three = One * Two;
print should probably take the stream to print to as std::ostream&. And I'd prefer it to be a free function instead of a member function. I would contemplate overloading operator<< instead of naming it print.
This wont be possible in C++03 but C++0x offers auto.
auto Three=Multiply(One,Two);
No, when using a class template, you have to specify all template arguments explicitly.
If your compiler supports it, you can use auto from C++0x instead:
auto Three=Multiply(One,Two);
In g++, you can enable C++0x support using the -std=c++0x flag.
Templates are used at compilation time and are used to implement static polymorphism. This means you should know everything about your objects at the moment your code is being compiled.
Hence, here the compiler fails, because this would be too hard for it to know that Three should have (2,5) dimensions (at least at currently common standard).
If this is a question for "just-to-know", then OK, but in real code you should obviously use constructors to initialize matrix (and set it's dimensions).
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?