This question already has answers here:
C++ Memoization understanding
(3 answers)
Writing Universal memoization function in C++11
(5 answers)
Closed 8 years ago.
Consider the following code (compiles with gcc 4.7.2):
#include<iostream>
#include<memory>
struct Base
{
~Base() {}
virtual double operator()(double x) const = 0;
};
template<typename F, typename G> struct Compose;
struct A : public Base
{
virtual double operator()(double x) const {return x;} //suppose this is a hard-to.calculate function, lots of temporaries, maybe also time-dependent, etc
template <typename F>
Compose<A,F> operator()(const F& f) const {return Compose<A,F>(*this,f);}
};
struct B : public Base
{
virtual double operator()(double x) const {return x*x;} //suppose this is a hard-to.calculate function, lots of temporaries, maybe also time-dependent, etc
template <typename F>
Compose<B,F> operator()(const F& f) const {return Compose<B,F>(*this,f);}
};
struct C : public Base
{
virtual double operator()(double x) const {return x*x*x;} //suppose this is a hard-to.calculate function, lots of temporaries, maybe also time-dependent, etc.
template <typename F>
Compose<C,F> operator()(const F& f) const {return Compose<C,F>(*this,f);}
};
template<typename F, typename G>
struct Compose : public Base
{
Compose(const F &_f, const G &_g) : f(_f), g(_g) {}
F f;
G g;
virtual double operator()(double x) const {return f(g(x));}
};
int main()
{
double x=2.0;
A a;
B b;
C c;
std::shared_ptr<Base> ptrBase = std::make_shared<A>(A());
std::shared_ptr<A> ptrA = std::make_shared<A>(a);
std::cout<< a(x) <<std::endl;
std::cout<< ptrBase->operator()(x) <<std::endl;
std::cout<< ptrA->operator()(x) <<std::endl;
std::cout<< b(a(x)) <<std::endl;
std::cout<< c(b(a(x))) <<std::endl;
std::cout<< a(c(b(a(x)))) <<std::endl;
std::cout<< ptrA->operator()(c(b(ptrBase->operator()(x)))) <<std::endl;
}
Output:
2
2
2
4
64
64
64
Ok, long prelude for a short question. Several redundant calculations occur here, for instance, the result of A()(x) is calculated six times (some via objects, some via pointers). How can I implement a global output array which stores the evaluated function values?
One approach which came to my mind and should work is to implement a function std::string id() unique to each (composed) class, plus a global std::map<std::string,double> to store the results, and then check whether a (current) result exists.
Do you see other and maybe better approaches here? Thanks in advance.
Sorry guys, although there are some similarities (the word "memoization" which seems to somehow trigger a reflex), I really don't see why this should be duplicate ... but I'm open to discussion.
The case above is in my opinion much more complex than those in the linked threads (e.g., its not simply a fibonacci-function). Moreover, as far I can see the highlighted memoization class will treat objects and pointers differently (at least without further editing). My intention was to arrive at a pattern in which each result is calculated only once, regardles how it is invoked.
Up to now, I was playing around with CRTP'ed static results classes, which leads to the following code (compiles with gcc 4.7.2.):
#include<iostream>
#include<memory>
#include<string>
#include<map>
struct Base
{
virtual ~Base() {}
virtual double operator()(double x) const = 0;
virtual std::string id() const = 0;
};
template<typename F, typename G> struct Compose;
template<typename T>
struct Result
{
virtual ~Result() {}
double get(double x) const
{
return mem.find(x)->second;
}
bool isSet(double x) const {it=mem.find(x); return it!=mem.end();}
//get the previously found result by isSet(x)
double get() const
{
return it->second;
}
protected:
//the set function is const, as it works only on static variables
//don't know whether it is the best idea, but it allows for a const operator() later...
void set(double x, double y) const
{
mem.insert(std::make_pair(x,y));
}
private:
static std::map<double, double> mem;
static std::map<double, double>::const_iterator it;
};
template<typename T> std::map<double, double> Result<T>::mem;
template<typename T> std::map<double, double>::const_iterator Result<T>::it=Result<T>::mem.begin();
struct A : public Base, public Result<A>
{
virtual double operator()(double x) const
{
if(isSet(x))
{
return get();
}
else
{
double y=x;
set(x,y);
std::cout<<"setA ";
return y;
}
}
template <typename F>
Compose<A,F> operator()(const F& f) const {return Compose<A,F>(*this,f);}
virtual std::string id() const {return "A";}
};
struct B : public Base, public Result<B>
{
virtual double operator()(double x) const
{
if(isSet(x))
{
return get();
}
else
{
double y=x*x;
set(x,y);
std::cout<<"setB ";
return y;
}
}
template <typename F>
Compose<B,F> operator()(const F& f) const {return Compose<B,F>(*this,f);}
virtual std::string id() const {return "B";}
};
struct C : public Base, public Result<C>
{
virtual double operator()(double x) const
{
if(isSet(x))
{
return get();
}
else
{
double y=x*x*x;
set(x,y);
std::cout<<"setC ";
return y;
}
}
template <typename F>
Compose<C,F> operator()(const F& f) const {return Compose<C,F>(*this,f);}
virtual std::string id() const {return "C";}
};
template<typename F, typename G>
struct Compose : public Base, public Result<Compose<F,G> >
{
Compose(const F &_f, const G &_g) : f(_f), g(_g) {}
F f;
G g;
virtual double operator()(double x) const
{
if(this->isSet(x))
{
return this->get();
}
else
{
double y=f(g(x));
this->set(x,y);
std::cout<<"set"<<this->id()<<" ";
return y;
}
}
virtual std::string id() const {return f.id() + "(" + g.id() + ")";}
};
int main()
{
double x=2.0;
A a;
B b;
C c;
std::shared_ptr<Base> ptrBase = std::make_shared<A>(A());
std::shared_ptr<A> ptrA = std::make_shared<A>(A());
std::cout<<"-------------------------------"<<std::endl;
std::cout<< a(x) <<std::endl;
std::cout<<ptrBase->operator()(x) <<std::endl;
std::cout<<ptrA->operator()(x) <<std::endl;
std::cout<<"-------------------------------"<<std::endl;
std::cout<<c(x)<<std::endl;
std::cout<<C()(x)<<std::endl;
std::cout<<C()(x)<<std::endl;
std::cout<<"-------------------------------"<<std::endl;
auto ba= b(a);
std::cout<<ba(x) << std::endl;
auto cba= c(ba);
std::cout<<cba(x)<< std::endl;
auto acba= a(cba);
std::cout<<acba(x)<<std::endl;
}
Output:
-------------------------------
setA 2
2
2
-------------------------------
setC 8
8
8
-------------------------------
setB setB(A) 4
setC(B(A)) 64
setA(C(B(A))) 64
-------------------------------
Ok, some things to note here:
By inheritance from the static results class, it is interesting how all the differently called A's (by object, by pointer-to-object, by pointer-to-base) retrieve the stored result (there is only one set). Same for C() which is called three times but set only once.
In order to anticipate the next reflex, I know that multiple inheritance can be bad, but the classes seem to be well separated. The same behavior is probably obtained by composition, so please forget about that point.
In fact, this isn't really a memoization class yet, as it simply stores the result which was calculated first. Thus it also gives wrong results [eg. for C(B(A))]. However, this can be easily cured by a map or whatever. I will do this later eventually, at the moment its only about the pattern (EDIT: is done).
And as a last point, I'm aware that a different solution than in the seemingly-duplicated threads doesn't imply a different questions. Yet, it will maybe (--hopefully) yield some extension of the memoization-topic on this page from which all can benefit.
I'm looking forward to your thoughts. Thanks in advance!
EDIT 2: Helping yourself is a good thing, now the code works as I was looking for. I have updated it in the post above.
Changes:
Added a map to actually make a real memoization class out of it. Caution: double comparison is dangerous, so one should better pass a more approriate comparison function instead of the standard equality.
Made the static members of the results array private, and the setters protected, as only the function-classes may change the results.
Still the map types are not given by template parameters (as in the linked threads). That is overhead which I don't need (and probably YAGNI too).
Now I'll stop talking to myself. Comments are still welcome. Thanks, David
Related
I have a hash process implemented using Howard Hinnant's method (generic hash based on hash_append overloads).
The purpose of that method is to create hash of classes in order to "memoize" result of computations (see end of this answer), so I am facing some issue. In particular, consider the following possible Input class that needs to be hashed:
struct A {
virtual int do_stuff() const = 0;
virtual ~A();
};
struct B: A {
int do_stuff() const override { return 0; }
};
struct C: A {
const int u;
int do_stuff() const override { return u; }
};
struct Input {
A const& a; // store a reference to an instance of B or C
};
Now, if I want to hash Input, I will have something like:
template <class HashAlgorithm>
void hash_append(HashAlgorithm& h, Input const& input) {
hash_append(h, typeid(input));
hash_append(h, typeid(input.a));
}
So I need an overload of hash_append for A:
template <class HashAlgorithm>
void hash_append(HashAlgorithm& h, A const& a) {
hash_append(h, typeid(a));
}
The problem here is that depending on the runtime type of a, I would need to add extra information to the hash, e.g. for C I would need to add u.
I thought about the following solutions (and drawbacks):
add a virtual method to A that returns a specific value that can be added to the typeid() hash, but:
this means adding a method inside A that is not related to the purpose of A, thus I don't really like this idea (in particular because I have multiple A-like classes);
this breaks the concept of hash_append since the method will have a unique return type for all inheriting classes.
do a bunch of dynamic_cast inside hash_append:
I found this pretty ugly... in particular if I have multiple classes similar to A;
this is error-prone: if someone adds a new children of A and do not add a dynamic_cast inside hash_append.
Is there a way to hash a polymorphic type, without having to modify the type itself or rely on a bunch of dynamic_cast?
The final goal of this is to be able to memoize results of some heavy functions. Let's sketch the basic structure of my application:
struct Input { };
struct Result { };
Result solve(Input const&);
The solve function is computationally-heavy, so I want to save the results of previous computation in file using hash of Inputs, e.g. something like:
// depends on hash_append
std::string hash(Input const&);
Result load_or_solve(Input const& input) {
auto h = hash(input);
Result result;
if (exists(h)) { // if result exists, load it
result = load(h);
}
else { // otherwize, solve + store
result = solve(input);
store(h, result);
}
return result;
}
The load and store methods would load and store results from files, the goal is to memoize solutions between different runs.
If you have suggestion on how to memoize these results without having to deal with the above issues, I'll be glad to read them.
You can use double dispatching within the hash_append version of A and forward the request to the proper version (that is the one either for B or C). The drawback is that you must add boilerplate to those classes to accept a visitor and I cannot say if it's acceptable for you.
Here is a bunch of code that should illustrate the idea:
struct B;
struct C;
struct Visitor {
virtual void visit(const B &) = 0;
virtual void visit(const C &) = 0;
};
template<typename T, typename... O>
struct HashVisitor: T, HashVisitor<O...> {
template<typename U>
std::enable_if_t<std::is_same<T, U>::value> tryVisit(const U &u) {
T::operator()(u);
}
template<typename U>
std::enable_if_t<not std::is_same<T, U>::value> tryVisit(const U &u) {
HashVisitor<O...>::visit(u);
}
void visit(const B &b) override { tryVisit<B>(b); }
void visit(const C &c) override { tryVisit<C>(c); }
};
template<>
struct HashVisitor<>: Visitor {};
template<typename... F
auto factory(F&&... f) {
return HashVisitor<std::decay_t<F>>{std::forward<F>(f)...};
}
struct A {
virtual void accept(Visitor &) = 0;
virtual int do_stuff() const = 0;
virtual ~A();
};
struct B: A {
void accept(Visitor &v) override { v.visit(*this); }
int do_stuff() const override { return 0; }
};
struct C: A {
const int u;
void accept(Visitor &v) override { v.visit(*this); }
int do_stuff() const override { return u; }
};
template <class HashAlgorithm>
void hash_append(HashAlgorithm &, const B &) {
// do something
}
template <class HashAlgorithm>
void hash_append(HashAlgorithm &, const C &) {
// do something
}
template <class HashAlgorithm>
void hash_append(HashAlgorithm &h, const A &a) {
auto vis = factory(
[&h](const B &b){ hash_append(h, b); },
[&h](const C &c){ hash_append(h, c); }
);
a.accept(vis);
}
I wanted to create a simple template class having a member variable ret. For some reason my MSVC 2010 compiler complains, that there is no declared variable named ret in Converter<double>. I'm really clueless, why?
template<typename M>
struct Converter {
M ret;
void operator()(const int& value) {
throw std::exception("Not implemented!");
}
};
template<>
struct Converter<double> {
void operator()(const int& value) {
ret=value;
}
};
int main() {
Converter<int> x;
}
This is another class (there is no inheritance or any other depenency here):
template<>
struct Converter<double> {
double ret;
void operator()(const int& value) {
ret=value;
}
};
I know this is already marked solved, but I thought I should just clarify this further.
Converter<double> and Converter<int> are different separate classes, so ret would not be defined in your double variation until you declare it as one of its members.
Regardless, it appears what you're trying to achieve is inheritance, which can be done in a similar way:
template<typename M>
struct AbstractConverter { // you could call it 'Converter' too, and it'll work as you expect
M ret;
virtual void operator()(const int& value) {
throw std::exception("Not implemented!");
}
//or
virtual void operator(const int &value) = 0; //pure virtual
// will not compile if someone wants to use it directly
};
template<>
struct Converter<double> : public AbstractConverter<double>{
void operator()(const int& value) { // we implement the operator here
ret=value;
}
};
I have the following abstract base class:
class Function {
virtual double Eval(double x) const = 0;
};
I want to be able to use expressions like f * g or f->operator *(g), where f and g are concrete objects of the class Function, in my main file, say for example when I want to calculate a definite integral so that I can write:
AnIntegrationMethod(f*g);
A rather unsophisticated method I came up with consists of declaring a class Product (only header file shown, the implementation is obvious):
class Product: public Function {
public: Product(Function *g, Function *f);
~Product();
virtual double Eval(double x) const; //return _g->Eval(x)*_f->Eval(x)
private: Function *_g; Function *_f;
};
and then in any of my functions
#include "Product.h"
class ConcreteFunction: public Function {
public:
ConcreteFunction();
~ConcreteFunction();
virtual double Eval(double x) const;
Function* operator*(Function *f) {return new Product(this, f);}
};
This actually works for simple stuff but the problem is that the operator * is only defined within single derived classes of the base class instead of being defined for every possible derived class. This means, for instance, that if I have a concrete object f representing a mathematical function I can call f->operator *g but if I want to call again the operator * to get the object (f->operator * g)->operator * f I am not going to be able to because the function f* g does not have the * operator defined as f.
I suppose I should define the operator * directly in my base class but then I can't figure out how to implement the operator because I don't really know how to get the proper Eval function for the product since I cannot use the class Product now, it wouldn't make sense to use the class Product derived from the class Function in the class Function itself. I think I'm also quite confused over whether in general is correct to write something like the following:
Function* Function::operator*(Function *f) {
Function *g;
...
//operations that allow g to be have the right Eval function
//which should of the sort this->Eval(x) * f->Eval(x)
...
return g;
}
Any hints or suggestions on how to proceed are appreciated. My level is very basic, I've been programming two month now.
Just a sketch, you might do something like this:
#include <memory>
// Base Function: f(x) = x
class Function
{
protected:
struct Implementation
{
virtual ~Implementation() {}
virtual double evaluate(double x) const { return x; }
};
public:
Function()
: self(std::make_shared<Implementation>())
{}
double operator () (double x) const { return self->evaluate(x); }
protected:
Function(std::shared_ptr<Implementation> self)
: self(self)
{}
private:
std::shared_ptr<Implementation> self;
};
typedef Function Identity;
// Unary Function: u(-f(x))
class UnaryMinus : public Function
{
protected:
struct Implementation : Function::Implementation
{
Function f;
Implementation(Function f)
: f(f)
{};
virtual double evaluate(double x) const override { return -f(x); }
};
public:
UnaryMinus(Function f)
: Function(std::make_shared<Implementation>(f))
{}
};
// Binary Function: u(f(x) + g(x))
class BinaryAdd : public Function
{
protected:
struct Implementation : Function::Implementation
{
Function f;
Function g;
Implementation(Function f, Function g)
: f(f), g(g)
{};
virtual double evaluate(double x) const override { return f(x) + g(x); }
};
public:
BinaryAdd(Function f, Function g)
: Function(std::make_shared<Implementation>(f, g))
{}
};
// Binary Function: u(f(x) * g(x))
class BinaryMultiply : public Function
{
protected:
struct Implementation : Function::Implementation
{
Function f;
Function g;
Implementation(Function f, Function g)
: f(f), g(g)
{};
virtual double evaluate(double x) const override { return f(x) * g(x); }
};
public:
BinaryMultiply(Function f, Function g)
: Function(std::make_shared<Implementation>(f, g))
{}
};
inline UnaryMinus operator - (Function f) { return UnaryMinus(f); }
inline BinaryAdd operator + (Function f, Function g) { return BinaryAdd(f, g); }
inline BinaryMultiply operator * (Function f, Function g) { return BinaryMultiply(f, g); }
#include <iostream>
int main() {
Identity x;
Function result = -x * (x + x) + x;
std::cout << result(2) << '\n';
}
You could overload operator* as a free-standing function. Put it in Product.h/cpp even if it is not a member of Product, since it is tightly related to it.
In Product.h:
Function* operator*(Function *f, Function *g);
In Product.cpp:
Function* operator*(Function *f, Function *g) {
return new Product(f, g);
}
Same with addition, subtraction, etc.
Alternatively, you can implement them as member functions, but put the definition in Function.cpp and include Product.h, etc. there.
Note that your design has a huge flaw. You create new Function objects on the heap and pass around pointers. You need to delete them somewhere in your code, I assume in your deconstructors. But then you also need to take care about copying your objects. Usually, it is a nightmare to care about proper deletion manually, and there are automatic ways to do it (called "memory management"). You could consider using smart pointers, for example. Have a look at std::shared_ptr. While not being most efficient in every case, it is a good thing to use in general when you first want to learn the language and not too many details about memory management. To apply shared_ptr to your code, replace every Function* with shared_ptr<Function>, and replace new Function(...) with make_shared<Function>(...) (and the same with other types).
Also note that * for math functions is ambiguous: In some contexts / literature, f*g means multiplying the result, while in others it means function convolution.
Here's a C++11 generic programming solution that doesn't rely on inherited polymorphism (i.e. - virtual functions) and doesn't require dynamic allocation.
I'm not a C++ expert and this can likely be improved upon significantly, but it works and gets the idea across. In particular, the code below only works for functions of double's. You can probably make the operands and return types be a template type too, so that this can generically work on different types (e.g. - complex) too. I don't know the proper way to scope the template operators so that you can use the shorthand operator notation and not have them accidentally invoked on (or make ambiguous) other types that have operator()(double x). If anyone has any suggestions to improve upon this answer, then please chime in and I'll edit my answer.
#include <iostream>
using namespace std;
struct Identity
{
double operator() (double x) const { return x; }
};
struct Constant
{
template<typename T1>
Constant(const T1 &x) : _x(x) {}
double operator()(double x) const { return _x; }
private:
double _x;
};
template<typename T1>
struct Negate
{
Negate(const T1 &f) : _f(f) {}
double operator() (double x) const { return -_f(x); }
private:
T1 _f;
};
template<typename T1>
struct Reciprocal
{
Reciprocal(const T1 &f) : _f(f) {}
double operator() (double x) const { return 1 / _f(x); }
private:
T1 _f;
};
template<typename T1, typename T2>
struct Sum
{
Sum(const T1 &f, const T2 &g) : _f(f), _g(g) {}
double operator() (double x) const { return _f(x) + _g(x); }
private:
T1 _f;
T2 _g;
};
template<typename T1, typename T2>
struct Product
{
Product(const T1 &f, const T2 &g) : _f(f), _g(g) {}
double operator() (double x) const { return _f(x) * _g(x); }
private:
T1 _f;
T2 _g;
};
template<typename T1>
Negate<T1> operator-(const T1 &f)
{ return Negate<T1>(f); }
template<typename T1, typename T2>
Sum<T1, T2> operator+(const T1 &f, const T2 &g)
{ return Sum<T1, T2>(f, g); }
template<typename T1, typename T2>
Sum<T1, Negate<T2> > operator-(const T1 &f, const T2 &g)
{ return Sum<T1, Negate<T2> >(f, Negate<T2>(g)); }
template<typename T1, typename T2>
Product<T1, T2> operator*(const T1 &f, const T2 &g)
{ return Product<T1, T2>(f, g); }
template<typename T1, typename T2>
Product<T1, Reciprocal<T2> > operator/(const T1 &f, const T2 &g)
{ return Product<T1, Reciprocal<T2> >(f, Reciprocal<T2>(g)); }
int main()
{
auto f = (Identity() * Constant(4.0) + Constant(5)) / Identity(); // f(x) = (x * 4 + 5) / x; f(2) = 6.5
auto g = f * f; // g(x) = f(x) * f(x); g(2) = 42.25
cout << f(2) << " " << g(2) << " " << (g / f)(2) << endl; // prints 6.5 42.25 6.5
return 0;
}
EDIT: The main drawback of this approach is that the type of a "formula" must be fully known at compile time and embedded in the template generated classes. That means that very complicated formulas will generate lots of different classes and code. So, this approach could lead to nasty code bloat. Also, you can't do something like:
for (i = 1; i < j; ++i) // raise f to the jth power (other than 0)
f *= f;
Since the type of f must be fully known at compile time and the multiplication is invoking new types iteratively. The other approaches that use a class hierarchy, dynamic allocation (with auto-cleanup) and polymorphism can do this though and don't have the problem of code bloat. Still, it was interesting to try.
I've got a class D, that I want to have classes A,B,C inherit from. However, the functions that I want to declare as pure virtual are templated.
Unfortunately, in the words of visual studio:
member function templates cannot be virtual
Classes A,B,C have a member operator called in the exact same manner, though may return different values (double or unsigned int namely. But I'd be happy to get it to work with just double):
template<typename T>
double operator()(T&, unsigned int b){/*code*/};
How could I properly create a polymorphic collection of classes A,B,C (similar to a std::vector<D*> that would work if I didn't want member function templates) that does what I'm trying to do?
EDIT:
An example of what I'd like to be able to do:
std::default_random_engine rng((unsigned int) std::time(0));
std::vector<D*> v;
v.push_back(new A(0.3));
v.push_back(new B(1.0,3.2));
v.push_back(new C);
for(auto x : v){
for(auto y : x->operator()(rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
I'm not entirely sure what you want to do, but if you move the template definition to the class instead of the method, everything is happy. Does that do what you want?
template<typename T>
class A
{
public :
virtual double operator() (T& t, unsigned int b) = 0;
};
template<typename T>
class B : public A<T>
{
public:
virtual double operator() (T& t, unsigned int b)
{
// code
}
};
EDIT:
Or, given that you don't want the template at the class level, what about moving the random calculation out of the polymorphic method, and then having a simple plymorphic method for the actual hard part. This assumes you only want to generate one random number, If you want more, you could always create a vector of random numbers, the size of which is determined in construction. Anyway the code below demonstrates what I am talking about:
class D
{
public :
template<typename T>
double operator() (T& t, unsigned int b)
{
double calc_rand = t();
return DoStuff(calc_rand, b);
}
protected :
virtual double DoStuff(double rnd_value, unsigned int b) = 0;
};
class A : public D
{
protected :
virtual double DoStuff(double rnd_value, unsigned int b)
{
return rnd_value * b;
}
};
int main(void)
{
std::random_device rd;
A a;
std::cout << a(rd, 5) << std::endl;
}
You'll most probably need to use delegates here. If all the classes have the same name and parameters, it's as easy as doing:
template <typename T>
class baseWrapper{
double method(T& a, unsigned int b) = 0;
};
template <typename T, typename myClass>
class wrapper: public baseWrapper<T>{
myClass &instance;
double method(T& a, unsigned int b){
return instance.method<T>(a,b);
};
wrapper(myClass &instance){this->instance = instance;};
};
And then you can create a collection of delegates:
std::vector<baseWrapper<int>*> vec;
A myObject1, B myObject2;
wrapper<int,A> wrapper1(myObject1);
wrapper<int,B> wrapper2(myObject2);
vec.push_back(&wrapper1);
vec.push_back(&wrapper2);
If the functions are named differently, you'll need to pass a function pointer as an additional parameter, or test it with SFINAE.
Perhaps you can implement a type erasure for the template parameter of the member functions. Going with your RNG example:
class RandUIntIfc {
public:
virtual ~RandUIntIfc() = 0;
virtual unsigned int min() const = 0;
virtual unsigned int max() const = 0;
virtual unsigned int operator()() = 0;
};
class RandUInt {
public:
template <typename RNG>
explicit RandUInt(RNG& rng);
unsigned int min() const;
unsigned int max() const;
unsigned int operator()();
private:
std::shared_ptr<RandUIntIfc> impl_;
template <typename RNG>
class Impl : public RandUIntIfc {
public:
explicit Impl(RNG& rng);
virtual unsigned int min() const;
virtual unsigned int max() const;
virtual unsigned int operator()();
private:
RNG& ref_;
};
};
I hope all the actual member definitions are obvious. That leaves just the change to D and code that uses it:
class D {
public:
virtual ~D() = 0;
virtual double operator()(RandUInt rng, unsigned int b) = 0;
};
std::default_random_engine rng((unsigned int) std::time(0));
RandUInt typeless_rng(rng);
std::vector<D*> v;
// ...
for(auto x : v){
for(auto y : x->operator()(typeless_rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
You shouldn't use a template function but just pass delegate to the rng through the virtual function. So basically you could do this:
class D
{
virtual double operator()(std::function<int()>, int)=0;
};
And call it like this:
std::default_random_engine rng;
std::vector<D*> v;
...
for(auto x : v)
{
std::cout << x->operator(std::bind(rng), 5) << ',';
}
In writing a program, I've come up with a piece of code that I cannot manage to make code-duplication free.
#include <iostream>
using namespace std;
class Presenter{
public:
template <typename T>
void addField(T& t){
cout << "do something that could happen to modify t" << endl;
}
template <typename T>
void addField(const T& t){
cout << "do something that cannot possibly happen to modify t" << endl;
}
};
class Presented{
public:
Presented() : a(0), b(0.) {}
void bind(Presenter& p){
p.addField(a);
p.addField(b);
//...
}
void bind(Presenter& p) const {
p.addField(a);
p.addField(b);
//...
}
private:
int a;
double b;
//...
};
int main() {
Presenter presenter;
Presented p1;
const Presented p2;
p1.bind(presenter);
p2.bind(presenter);
}
Here is a simple dummy program which shows the issue. As you see, the code of the two bind functions is (looks) exactly the same. Of course it is not, since two different functions (addField) are used, which only happen to share the name.
Nonetheless, I have been looking for a way to remove the need to verbatim write the void bind(Presenter& p) const.
Does anyone see a method for reaching the goal? I wasn't able to come up with one.
Delegate to a template that can be called with a const or a non-const instance of Presented:
class Presented{
public:
Presented() : a(0), b(0.) {}
void bind(Presenter& p){
bindImpl(p, *this);
}
void bind(Presenter& p) const {
bindImpl(p, *this);
}
private:
template<typename P>
static void bindImpl(Presenter& p, P& presented)
{
p.addField(presented.a);
p.addField(presented.b);
}
int a;
double b;
};