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);
};
Related
I'm creating a custom vector class for a school project and I'd like to be able to initialize it like this:
vector x = { 2, 3, 4, 5 };
Is there any way to do this is C++?
Here is the header of my class:
class vector {
private:
int vsize;
int valloc;
double* values;
public:
vector() : vsize(0), valloc(0), values(nullptr) {}
vector(???);
vector(const vector& v);
int size() const { return vsize; };
int alloc() const { return valloc; };
void resize(int newsize);
void insert(double x);
void insert(double x, int index);
double* value() const { return values; };
double value(int index) const { return *(values + index - 1); }
};
You can support that by adding a constructor that takes a std::initialzer_list<double>.
vector(std::initializer_list<double> init) : vsize(init.size()),
valloc(init.size()),
values(new double[init.size()])
{
std::copy(init.begin(), init.end(), values);
}
You can make that a bit more flexible by using a template.
template <typename T>
vector(std::initializer_list<T> init) : vsize(init.size()),
valloc(init.size()),
values(new double[init.size()])
{
std::copy(init.begin(), init.end(), values);
}
I'm having a problem to make the code:
void main(){
Matrix c(rows,cols);//rows & cols are int numbers
c[0][0]=2//the line that I'm having a problem to do the operator
}
//My class defined like this:
class Matrix{
public:
Matrix(int rows,int cols): rows(rows), cols(cols){
mat= new double*[cols];
for( int i=0; i<rows;i++){
*mat=new double[i];
}
}
private:
int rows,cols;
double **mat;
};
How can I make an operator that will help me to do the line that I'm having a problem with?
There are no operator [][], but operator[]. So that one should return something for which you can use [] too (pointer or proxy class).
In your case, you might simply do:
double* operator[](int i) { return mat[i]; }
const double* operator[](int i) const { return mat[i]; }
For more complicated cases, you have to return a proxy class.
Don't dynamically allocate in two dimensions like that. It's poison for your cache, and completely pointless. I see it all the time and I wish I didn't! Make yourself a nice std::vector<double> of size rows*cols instead.
Anyway, the trick to permit [width][height] is a proxy class. Have your operator[] return an instance of a class that has its own operator[] to do the second-level lookup.
Something like this:
#include <iostream>
#include <vector>
struct Matrix
{
Matrix(const size_t columns, const size_t rows)
: columns(columns)
, rows(rows)
, data(columns*rows, 0)
{}
size_t index(const size_t x, const size_t y) const
{
return x + y*columns;
}
double& at(const size_t x, const size_t y)
{
return data[index(x, y)];
}
double at(const size_t x, const size_t y) const
{
return data[index(x, y)];
}
template <bool Const>
struct LookupHelper
{
using ParentType = std::conditional_t<Const, const Matrix, Matrix>;
using ReturnType = std::conditional_t<Const, double, double&>;
LookupHelper(ParentType& parent, const size_t x) : parent(parent), x(x) {}
ReturnType operator[](const size_t y)
{
return parent.data[parent.index(x, y)];
}
const ReturnType operator[](const size_t y) const
{
return parent.data[parent.index(x, y)];
}
private:
ParentType& parent;
const size_t x;
};
LookupHelper<false> operator[](const size_t x)
{
return {*this, x};
}
LookupHelper<true> operator[](const size_t x) const
{
return {*this, x};
}
private:
const size_t columns, rows;
std::vector<double> data;
};
int main()
{
Matrix m(42, 3);
m[15][3] = 1;
std::cout << m[15][3] << '\n';
}
(In reality, you'd want to make it moveable and it could doubtlessly be tidied up a bit.)
Certainly, switching to operator() or a .at(width, height) member function is a lot easier…
Implementing operator[][] using proxy class. Works fine for single 2-dimensional data structure which can be accessed by some double data(int row, in col) method. However if I want to have few data methods I'd like to use pointer to member function which is stored in proxy inner-class TPatternRow:
class TLearnPattern
{
public:
typedef int (TLearnPattern::* IndexFunction)(int);
typedef double (TLearnPattern::* DataFunction)(int, int);
TLearnPattern(TDataSource *source);
class TPatternRow ///< Proxy class to implement operator[][]
{
public:
TPatternRow(TLearnPattern& source, int row, DataFunction func) :
lp(source),
i(row),
data(func)
{}
double& operator[](int j) { return (lp.*data)(i, j); }
private:
TLearnPattern& lp;
DataFunction data = &TLearnPattern::in;
int i;
};
TPatternRow operator [](int i) { return TPatternRow(*this, i, &TLearnPattern::in); }
TPatternRow In(int i) { return TPatternRow(*this, i, &TLearnPattern::in); }
TPatternRow Out(int i) { return TPatternRow(*this, i, &TLearnPattern::out); }
virtual double in(int row, int col) final;
virtual double out(int row, int col) final;
}
How to syntactically correctly call following line?
double& operator[](int j) { return (lp.*data)(i, j); }
Use std::bind? How to correctly bind this in TPatternRow constructor?
And some related question: does bind works fast enough comparing to just pointer to member function call?
Solved like this:
double operator[](int j)
{
auto dataFunc = std::bind(data, lp, _1, _2);
return dataFunc(i, j);
}
or original without &:
double operator[](int j) { return (lp.*data)(i, j); }
Example code:
class Sum{
public:
void value(int val){_v = val;}
int add(int val){return _v + val;}
private:
int _v;
};
Sum sum;
sum.value(5);
int myResult = sum.add(10);
Is it possible to make the sum.add(10) default so I can get the same result like this:
int myArea = sum(10);
(I suspect the question title is wrong, perhaps it is the reason why I can't find a solution. Feel free to edit.)
Yes you can. What you can do is overload the operator() of the class to turn it into a functor. You can add
int operator()(int val) { return add(val); }
To the class and now sum(some_value) is the same thing as sum.add(some_value)
That's specifically what the function call operator is for.
class Sum{
public:
void value(int val){ _v = val; }
int add(int val) const{ return _v + val; }
// Function call operator
int operator()(int val) const {
return add(val);
}
private:
int _v;
};
int main()
{
Sum sum;
sum.value(5);
// Calls the function call operator
int myResult = sum(10);
}
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);
...