I would like to implement real functions in C++. In particular I would like to evaluate, differentiate, add, multiply such objects. Here is my implementation
class RealFunc {
public:
virtual int Eval(const double& x, double& result) = 0;
virtual int Diff(const double& x, double& result) = 0;
};
class Sqrt : public RealFunc {
public:
int Eval(const double& x, double& result);
int Diff(const double& x, double& result);
};
int Sqrt::Eval(const double& x, double& result) {
if(x<0) return 0;
else {
result = sqrt(x);
return 1;
}
};
int Sqrt::Diff(const double& x, double& result) {
if(x<=0) return 0;
else {
result = 0.5/sqrt(x);
return 1;
}
};
It gets tricky when I try to add RealFunc objects. I have to create a sum class that inherits from RealFunc
RealFunc operator+(const RealFunc& f, const RealFunc& g) {
Sum_RealFunc h(f,g);
return h;
};
class Sum_RealFunc : public RealFunc {
public:
Sum_RealFunc(const RealFunc& f_, const RealFunc& g_) : f(f_), g(g_) {};
int Eval(const double& x, double& result);
int Diff(const double& x, double& result);
private:
RealFunc f;
RealFunc g;
};
int Sum_RealFunc::Eval(const double& x, double& result) {
double temp_f,temp_g;
int success_f,success_g;
success_f = f.Eval(x,temp_f);
success_g = g.Eval(x,temp_g);
result = temp_f+temp_g;
return success_f*success_g;
};
// Same for Sum_RealFunc::Diff
My issue here is that I cannot use f,g as members in Sum_RealFunc since RealFunc is abstract... How should I proceed to get a clean implementation ?
PS : The code I put is a light version of what I am working on (functions from RxR->R with all differentiation directions, finite difference if stepsize member is not zero and other side functions)
The problem you are facing is that you need both a feature that works well with value objects (operator overloading) and features that only works with pointers (inheritance/polymorphism).
As a solution, you'd need to have a value object with overloaded operators as a wrapper for polymorphic objects managed via pointers:
class RealFuncImpl {
public:
virtual ~RealFuncImpl(); // don't forget this for polymorphic objects
virtual int Eval(const double& x, double& result) = 0;
virtual int Diff(const double& x, double& result) = 0;
};
class RealFunc {
std::shared_ptr<RealFuncImpl> impl;
public:
int Eval(const double& x, double& result);
int Diff(const double& x, double& result);
};
You'd derive your Sum_RealFuncImpl from RealFuncImpl and implement your operators for RealFunc. You should probably hide away your Impl classes in some "detail" namespace, as your code's end user should never see them.
EDIT:
Your Sum_RealFuncImpl would contain two std::shared_ptr<RealFuncImpl> members.
Try
class Sum_RealFunc : public RealFunc {
public:
Sum_RealFunc(RealFunc& f_, RealFunc& g_) : f(f_), g(g_) {};
int Eval(const double& x, double& result);
int Diff(const double& x, double& result);
private:
RealFunc& f;
RealFunc& g;
};
Now f and g are refernces instead which is fine.
Since you initialize them in the constructors initializer list, you can make the member variables references.
You have two possibilities:
Do as wolfgang suggested: use only a wrapper around a shared pointer. This way you can create copies without really having to copy the derived function objects.
Make the derived classes themselves copyable through a base-class pointer, by implementing a clone member. That's most conveniently done with deriving from a CRTP class instead of directly from the base class. I'd make it a local class, to not confuse things:
struct RealFunc {
virtual std::pair<double,bool> operator() //IMO better than this
(double x)const =0; // reference-argument hackery
virtual std::pair<double,bool> Diff
(double x)const =0;
virtual RealFunc* clone()const =0;
template<class Derived>
struct implementation : RealFunc {
RealFunc* clone() {
return new Derived(*static_cast<const Derived*>(this));
}
};
virtual ~RealFunc(){}
};
Now you just have to derive your function objects from implementation, to make them clonable:
struct Sqrt : RealFunc::implementation<Sqrt> {
std::pair<double,bool> operator()(double x) {
return x>=0
? std::make_pair(sqrt(x), true)
: std::make_pair(0., false);
}
...
}
Your sum function can now be done nicely with std::unique_ptr:
class Sum_RealFunc : public RealFunc::implementation<Sum_RealFunc> {
std::vector<std::unique_ptr<RealFunc>> summands;
public:
std::pair<double,bool> operator()(double x) {
double result=0;
for(auto& f: summands) {
auto r = (*f)(x);
if(r.second) result += r.first;
else return std::make_pair(0., false);
}
return std::make_pair(result, true);
}
Sum_RealFunc(const Sum_RealFunc& cpy) {
for(auto& f: cpy.summands)
summands.push_back(f->clone());
}
//friend operator+=(RealFunc& acc, const RealFunc& add); //doesn't work
};
Unfortunately, this is not enough indirection to allow writing simple sum expressions. I did something in a recent project that solved pretty much all of these issues, but was yet a bit more complicated: I gave every instance the option to override its behaviour with any other instance. Like
class RealFunc {
std::unique_ptr<RealFunc> override;
public:
virtual std::pair<double,bool> operator()(double x)const {
return (*override)(x);
}
virtual std::pair<double,bool> Diff(double x)const {
return override->Diff(x);
}
auto implemented() -> RealFunc* {
return implement_override? override->implemented() : this; }
auto implemented()const -> const RealFunc* {
return implement_override? override->implemented() : this; }
virtual RealFunc* clone()const =0;
template<class Derived>
struct implementation : RealFunc {
virtual std::pair<double,bool> operator()(double x)const =0;
virtual std::pair<double,bool> Diff(double x)const =0;
RealFunc* clone() {
return new Derived(*static_cast<const Derived*>(this));
}
};
virtual ~RealFunc(){}
};
That's not all, you need to include a lot of checks for override everywhere with this approach. But in the end, it allows you to combine functions very smoothly, like
RealFunc f = const_realfunc(7.);
for(auto& omega: omegas)
f += sine_angfreq(omega);
RealFunc g = f + noise_func(.3);
...
Related
General question :
If there are two objects A and B with respective functions f_A(arg list) and f_B(arg list).
What's the best way to create an object C with a function compounded of f_A(...) and f_B(...) ?
for example : f_C() = f_A() + f_B() or f_C() = f_A(f_B())
Is it possible to overload the "+" operator such that we can create the object C doing something like that ?
auto object_c = object_a + object_b
Here is a sample of my code :
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
)
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
GaussianKernel operator+(const GaussianKernel& b) {
/*Here I would like to overload the + operator such that
I can create a kernel from two others kernels,
I mean with a covariance function compound of the previous ones
*/
}
private:
double m_sigma;
double m_scale;
};
Thanks you.
Given two methods f_A and f_B you can get f_C returning the sum of the others by using for example a lambda:
auto f_C = [](/*param*/){ return f_A(/*param*/) + f_B(/*param*/); };
auto sum_result = f_C(param);
To get the compound method it would be this:
auto f_C = [](/*param*/){ return f_B( f_A(/*param*/)); };
auto compound_result = f_C(param);
PS: I know that this is not directly applicable to your example, still trying to find out what exactly you want to do.
I would start with prototype solution like this:
class FooKernel : public Kernel {
public:
FooKernel (std::function<double(double, double)> fun) : fun_(fun) {}
double covarianceFunction(
double X,
double Y
) const {
return fun_(X, Y);
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
std::function<double(double, double)> fun_;
};
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
) const
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
double m_sigma;
double m_scale;
};
No longer lambdas are used, but now uses Your function as You wished.
Later on I would try to remove the std::function as it may have quite big performance impact. Instead I would make the FooKernel a class template, that stores callable by value.
I would suggest another subclass of Kernel:
class CompoundGaussianKernel : public Kernel {
public:
CompoundGaussianKernel(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
: m_kernel1(kernel1), m_kernel2(kernel2)
{}
double covarianceFunction(double X, double Y)
{
return m_kernel1.covarianceFunction(X, Y) + m_kernel2.covarianceFunction(X, Y);
// or any other composition than "+"
}
private:
GaussianKernel m_kernel1;
GaussianKernel m_kernel2;
};
I recommend not to define operator+ inside of a class but as a free function.
CompoundGaussianKernel operator+(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
{
return CompoundGaussianKernel(kernel1, kernel2);
}
I've got a class which acts as a combiner of a vector of pointers to an abstract base class. In the combined class there is a lot of repetition of the function that is used to combine the member functions together, e.g.
class Base {
public:
virtual double foo1(double x) = 0;
virtual double foo2(double x) = 0;
};
class Combined : public Base {
std::vector< std::shared_ptr<Base> > bases;
public:
double foo1(double x) {
double rv = 0.0;
for( auto& b : bases ) {
rv += b->foo1(x);
}
return rv;
}
double foo2(double x) {
double rv = 0.0;
for( auto& b : bases ) {
rv += b->foo2(x);
}
return rv;
}
};
It feels like I should be able to write one function to abstract that pattern away from having to repeat it for every method, so the Combined could be written in a way such as
class Combined : public Base {
std::vector< std::shared_ptr<Base> > bases;
public:
double foo1(double x) {
return combiner(foo1, x);
}
double foo2(double x) {
return combiner(foo2, x);
}
};
and there would be a combiner function along the lines of
double combiner(FuncName f, double x)
{
double rv = 0.0;
for( auto& b : bases ) {
rv += b->f(x);
}
return rv;
}
To reduce the quantity of boilerplate
Any help would be greatly appreciated.
It's called std::accumulate (found in <numeric>) and it can do exactly this.
#include <iostream>
#include <memory>
#include <algorithm>
using namespace std;
struct iFoo {virtual double foo() const=0;};
struct A : public iFoo {virtual double foo() const{return 10;}};
struct B : public iFoo {virtual double foo() const{return 20;}};
std::vector<std::unique_ptr<iFoo>> foos;//pretend its a member variable i'm lazy
//pretend its a member function (again, lazy)
template <typename T,typename K>
T xform_accumulate(T init,K xformer)
{
return std::accumulate(foos.cbegin(),foos.cend(),init,[xformer](T a,const std::unique_ptr<iFoo>& b) {return a+xformer(b);});
}
int main()
{
foos.push_back(std::unique_ptr<iFoo>(new A()));
foos.push_back(std::unique_ptr<iFoo>(new B()));
double x = xform_accumulate( 0.0, [](const std::unique_ptr<iFoo>& x){return x->foo();});
cout << "Hello World" << x << endl;
return 0;
}
I have two classes in library:
class A
{
public:
int x;
};
template <class T>
class B : public A
{
public:
T y;
};
And have method:
... Method(A &a, A &b);
How compare y from a and b if a, b always have same type
B <T>
, but type of T unknown?
When you have a function,
Method(A a, A b);
You have lost the B part of the objects due to object slicing.
If you want retain the B part of the objects, you have to use references or pointers.
Method(A const& a, A const& b);
or
Method(A const* a, A const* b);
In order for Method to work correctly, you have to provide a way for the objects to be treated as B. You can use that using a virtual function in A.
class A
{
public:
int x;
virtual int compare(A const& rhs) const
{
return (this->x - rhs.x);
}
};
and make sure to override the function in B.
template <class T>
class B : public A
{
public:
T y;
virtual int compare(A const& rhs) const
{
// Use the base class first.
int r = A::compare(rhs);
// If the base class result is adequate, return.
if ( r != 0 )
{
return r;
}
// Do a dynamic_cast of the rhs.
B const* rhsPtr = dynamic_cast<B const*>(&rhs);
// If the dynamic_cast didn't succeed, need
// to figure out how to handle the case.
if ( rhsPtr == nullptr )
{
// Add error handling code
}
return (this->y - rhsPtr->y);
}
};
Then, in Method,
Method(A const& a, A const& b)
{
int r = a.compare(b);
}
A possible solution is to create a virtual function that will do the comparison.
Inside the body of the implementation in the derived class the type T is known and you'll have no problems.
struct Base {
...
virtual bool same_y(const Base& other) const = 0;
};
template<typename T>
struct Derived : Base {
T y;
virtual bool same_y(const Base& other) const {
return dynamic_cast< const Derived<T>& >(other).y == y;
}
};
You could define Method as a template method.
template<typename T>
bool Method(const A& a, const A& b)
{
const B<T>& first = dynamic_cast<const B<T>&>(a);
const B<T>& second = dynamic_cast<const B<T>&> (b);
return first.y == second.y;
}
With this approach you don't have to know the type of T inside Method. But you have to specify T when you call it:
bool areEqual = Method<int>(a, b);
Maybe that is no problem in your case.
Be aware that whenever you assign a B<T> to a variable of type A you are loosing the information that is specific to B<T> (in this case the value of y is lost). That's why I changed the signature of Method in order to take references instead of values.
It is possible to write a wrapper that takes any type that supports a certain operation, e.g.
#include <iostream>
class Houdini
{
struct I_Houdini_Impl
{
virtual void foo_impl(int x) const = 0;
virtual ~I_Houdini_Impl() { }
};
template <typename T>
struct Houdini_Impl : I_Houdini_Impl
{
Houdini_Impl(T const & t) : m_t(t) { }
void foo_impl(int x) const { m_t.foo(x); }
T m_t;
};
public:
template <typename T>
Houdini(T const & t) : m_impl(new Houdini_Impl<T>(t)) { }
void foo(int x) const { m_impl->foo_impl(x); }
protected:
private:
std::unique_ptr<I_Houdini_Impl> m_impl;
};
class A
{
public:
void foo(int x) const { std::cout << "A::foo(" << x << ")" << std::endl; }
};
class B
{
public:
template <typename T>
char foo(T const & t) const { std::cout << "B::foo(" << t << ")" << std::endl; return 'B';}
};
void houdini()
{
A a;
B b;
Houdini ha(a);
Houdini hb(b);
ha.foo(7);
hb.foo(8);
}
I can wrap anything in the Houdini-class that supports a const-method foo that can be called wih an int, regardless if it is an ordinary member function (as in class A) or a function template (as in class B) (and lets disregard for now that Houdini should exhibit value sematics). So far so good, but what I would like to do is to write a wrapper that supports binary operations, e.g. to write a wrapper that accepts any type and you can, say, add any two wrappers as long as the wrapped objects can be added and returns the wrapped return object from the addition:
class A { };
class B { };
class C { };
C operator+(A, B) { return C(); }
class Randi
{
public:
template <typename T> Randi(T ) { }
/* magic stuff goes here */
};
void randi()
{
A a;
B b;
Randi ra(a);
Randi rb(b);
Randi rc = ra + rb;
// rc is a Randi-object that wraps an object of type C
}
If I know in advance what types I am going to store I can do it by writing visitors but that is exactly what I do not want to do. I would need to unwrap both objects, try to call operator+ on the two unwrapped objects and wrap the result again but I cannot figure out how to do that.
Consider following
class Number
{
virtual Number* sum(Number* other) = 0;
};
class Int
: public Number
{
virtual Number* sum(Number* other)
{
// hard to implement since we doesn't know the type of other
}
};
class Double
: public Number
{
virtual Number* sum(Number* other)
{
// hard to implement since we doesn't know the type of other
}
};
We can do dynamic_casts in sum implementation to handle each case separately or we can use double dispatching.
class Double;
class Int;
class Number
{
public:
virtual Number* sum(Number* other) = 0;
protected
virtual Number* sum(Int* other) = 0;
virtual Number* sum(Double* other) = 0;
};
class Int
: public Number
{
virtual Number* sum(Number* other)
{
return other->sum(this);
}
virtual Number* sum(Int* other)
{
// implement int + int
}
virtual Number* sum(Double* other)
{
// implement int + double
}
};
class Double
: public Number
{
virtual Number* sum(Number* other)
{
return other->sum(this);
}
virtual Number* sum(Int* other)
{
// implement double + int
}
virtual Number* sum(Double* other)
{
// implement double + double
}
};
In bot cases implementations should be aware about all derived classes. This means that analog of Houdini_Impl for Randi class should know about all other types that may be passed to Randi's constructor which is impossible.
I am using GNU Scientific Library in my C++ project. For convience, I would like to trasparently wrap gsl_vector* in a C++ class (to add a bunch of domain specific functions and to simplify interface). But I am getting perplexed with how to deal with const gsl_vector*. Let me explain. Let me start with this minimalistic wrapper.
class Vector {
gsl_vector* vector_;
public:
Vector(gsl_vector* vector): vector_(vector) {}
double& operator()(int i) {
return *gsl_vector_ptr(vector_, i);
}
};
Suppose, further, that I have two functions. One is defined as follows:
int f(Vector& x) {
\\ do some math, e.g. x(0) = 0.0;
return 0;
}
Another one is a callback function that has to use GSL types, and is defined as follows:
int gsl_f(gsl_vector* x) {
Vector xx(x);
return f(xx);
}
This works fine. Now, suppose the callback has a constant signature:
int gsl_f(const gsl_vector* x);
Then I can redefine my Vector class and my f function accordingly:
class Vector {
const gsl_vector* vector_;
public:
Vector(const gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_const_ptr(vector_, i);
}
};
int f(const Vector& x) {
\\ do some math
return 0;
}
Also works. Now, I want my wrapper class to suit both situations. For example, I want to be able to do the following, preserving the safety of const:
int f(const Vector& x, Vector& y) {
\\ do some math
return 0;
}
int gsl_f(const gsl_vector* x, gsl_vector* y) {
Vector yy(y);
return f(x, yy);
}
I can do it by having a Vector with two pointers, const and non-const, and remembering whether it was initialized from a const or non-const member. My question is, can I do it without runtime checks? After all, all the information is there at the compile time.
Proposal (not wonderful, but should work):
class Vector {
gsl_vector* vector_;
const gsl_vector* const_vector_;
public:
Vector(const gsl_vector* vector): vector_(nullptr), const_vector_(vector) {}
Vector(gsl_vector* vector): vector_(vector), const_vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(const_vector_, i);
}
double& operator () (int i) {
return *gsl_vector_ptr(vector_, i);
}
};
Second possibility:
class Vector {
private:
gsl_vector* vector_;
Vector(gsl_vector* vector): vector_(vector) {}
public:
static const Vector* Create (const gsl_vector* vector) {
return new Vector (const_cast<Vector *> vector);
}
static Vector* Create (gsl_vector* vector) {
return new Vector (vector);
}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
double& operator () (int i) {
return *gsl_vector_ptr(vector_, i);
}
};
Combining both classes should work as expected, have you tried it?
class Vector {
gsl_vector* vector_;
public:
Vector(gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
double& operator()(int i) {
return *gsl_vector_ptr(vector_, i);
}
operator const_Vector()
{
return const_Vector(vector_);
}
};
class const_Vector {
const gsl_vector* vector_;
public:
const_Vector(const gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
};
Function signature needs to look this way:
int f(const_Vector& x, Vector& y) {
\\ do some math
return 0;
}
This followes a similar scheme like the iterator and const_iterator.
Maybe you have a situation which this will not work,. you should post this situation and we can try to solve it.
You can also use some kind of inheritance with pointer to data. further - templates can be used to create overloaded function returning either one or second version depending on input pointer types.
class JSONChannelFullConfigConst:
public JSONObjectRenderer {
public:
JSONChannelFullConfigConst(const uint8_t * channel_id,
const sensors_single_channel_config_t * cfg) :
j_channel_id(channel_id),
j_cfg(cfg) {
}
private:
const uint8_t * const j_channel_id;
const sensors_single_channel_config_t * const j_cfg;
void renderFields(rlf::UcOstreamBase& os) const;
public:
uint8_t getId() const {
return *j_channel_id;
}
};
class JSONChannelFullConfig:
public JSONChannelFullConfigConst,
public JSONObjectParser {
public:
JSONChannelFullConfig(uint8_t * channel_id, sensors_single_channel_config_t * cfg) :
JSONChannelFullConfigConst(channel_id, cfg),
j_channel_id(channel_id),
j_cfg(cfg) {
}
void setId(uint8_t id) {
*j_channel_id = id;
}
private:
uint8_t * const j_channel_id;
sensors_single_channel_config_t * const j_cfg;
virtual bool parseNameValuePair(const char * name, rlf::UcIstream & value);
};