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);
}
Related
Considering the following toy example, where I declare a class which encapsulates ublas from boost libraries:
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <iostream>
namespace ublas = boost::numeric::ublas;
class UblasEncapsulated {
public:
ublas::compressed_matrix<float>::reference operator()(int i, int j){
std::cout << "Non const reference" << std::endl;
MtrUpdated_ = true;
return mtr_(i, j);
}
ublas::compressed_matrix<float>::const_reference operator()(
int i, int j) const {
std::cout << "Const reference" << std::endl;
return mtr_(i, j);
}
UblasEncapsulated() { MtrUpdated = false; }
private:
ublas::compressed_matrix<float> mtr_(3, 3);
bool MtrUpdated_;
};
int main() {
UblasEncapsulated foo;
foo(2, 0) = 1.0f;
float const foo_float = foo(2, 0);
return 0;
}
I was expecting the output
Non constant reference
Constant reference
But I got
Non constant reference
Non constant reference
What am I doing wrong? How can I properly track when mtr_ could have its values changed?
foo is non-const, so the non-const version of foo.operator() will be called. It doesn't matter how the value it returns is used.
If you really want to know that MtrUpdated_ is only set true if an element is actually assigned to, you will need to use a proxy class:
class UblasEncapsulated {
public:
class proxy {
public:
proxy(UblasEncapsulated* ptr, int i, int j)
: ptr_(ptr), i_(i), j_(j)
{}
proxy& operator=(float f) {
ptr_->MtrUpdated_ = true;
ptr_->mtr_(i_, j_) = f;
return *this;
}
operator float() {
return ptr_->mtr_(i_, j_);
}
private:
UblasEncapsulated* ptr_;
int i_;
int j_;
};
proxy operator()(int i, int j) {
return proxy(this, i, j);
}
ublas::compressed_matrix<float>::const_reference operator() (int i, int j) const {
return mtr_(i, j);
}
UblasEncapsulated()
: mtr_(3, 3),
MtrUpdated_(false)
{}
private:
ublas::compressed_matrix<float> mtr_;
bool MtrUpdated_;
};
Live Demo
Note that you should avoid using a proxy class if you can get away with it since it doesn't play nicely with things like auto or template argument deduction.
I am using a base class and a child class defined above main in main.cpp
this gives me an error of undefined reference FactoryTraversal::AddPoint::AddPoint(int const&, int const&, int)'
Here is the code:
#include <iostream>
#include <list>
#include <typeinfo>
#include <cmath>
enum traversal_type
{
TRAVERSAL = 0,
TRAVERSALMAX
};
template <class T>
class FactoryTraversal
{
public:
FactoryTraversal();
FactoryTraversal *CreateInstance(const traversal_type &type);
virtual ~FactoryTraversal();
const std::list<int>& GetIndices() const {return indices;}
int GetIndicesSize() const {return indices.size();}
virtual void AddPoint(const T &x, const T &y, int index);
protected:
std::list<int> indices;
};
template<class T>
class Traversal : public FactoryTraversal<T>
{
public:
Traversal();
void AddPoint(const T &x, const T &y, int index);
int GetResultXOR() const {return result_xor;}
private:
T coords_s[2];
T coords_e[2];
int result_xor;
void update_result(int index);
T calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2);
};
template<class T>
Traversal<T>::Traversal():FactoryTraversal<T>()
{
//Do nothing
}
template<class T>
void Traversal<T>::AddPoint(const T &x, const T &y, int index)
{
if (0 == this->GetIndicesSize())
{
this->indices.push_front(index);
coords_s[0] = x; coords_s[1] = y;
coords_e[0] = x; coords_e[1] = y;
}
else
{
T d1 = this->calculate_distance(x,coords_s[0],y,coords_s[1]);
T d2 = this->calculate_distance(x,coords_e[0],y,coords_e[1]);
if (d1 < d2)
{
this->indices.push_front(index);
coords_s[0] = x; coords_s[1] = y;
}
else
{
this->indices.push_back(index);
coords_e[0] = x; coords_e[1] = y;
}
}
this->update_result(index);
}
template<class T>
T Traversal<T>::calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2)
{
if (typeid(T) == typeid(int))
{
return std::min(std::abs(x1-x2),std::abs(y1-y2));
}
return 0;
}
template<class T>
void Traversal<T>::update_result(int index)
{
if (0 == this->GetIndicesSize())
result_xor = index;
else
result_xor ^= index;
}
template<class T>
FactoryTraversal<T>::FactoryTraversal()
{
indices.clear();
}
template<class T>
FactoryTraversal<T>::~FactoryTraversal()
{
//Do Nothing
}
template<class T>
FactoryTraversal<T>* FactoryTraversal<T>::CreateInstance(const traversal_type &type)
{
if (TRAVERSAL == type)
return new Traversal<T>();
else
return NULL;
}
FactoryTraversal<int> factory_traversal;
Traversal<int> *traversal = new Traversal<int>();
int main()
{
int T;
std::cin>>T;
int output[T];
for (int i = 0; i < T; ++i)
{
int N;
std::cin>>N;
FactoryTraversal<int> factory_traversal;
FactoryTraversal<int> *traversal = factory_traversal.CreateInstance(TRAVERSAL);
for (int j = 0; j < N; ++j)
{
int x, y;
std::cin>>x>>y;
traversal->AddPoint(x,y,j+1);
}
Traversal<int> *tmp = dynamic_cast<Traversal<int> *>(traversal);
if (tmp)
output[i] = tmp->GetResultXOR();
else
output[i] = 0;
}
for (int i = 0; i < T; ++i)
{
std::cout<<output[i]<<std::endl;
}
return 0;
}
Interfaces in C++ are called "abstract classes", and classes are abstract if they have at least one "pure virtual function". A function is a pure virtual function if it is prefixed with virtual and has a trailing =0 in its declaration. This is what you want for FactoryTraversal::AddPoint:
virtual void AddPoint(const T &x, const T &y, int index) = 0;
Now the derived class is expected to define it (and it does). Without AddPoint being pure virtual, you are forced to provide an implementation for it in the base class, which you could do simply as:
virtual void AddPoint(const T &x, const T &y, int index){}
This gives a "default" or fallback implementation for when a derived class chooses not to override the method. If it were pure virtual, the derived class is forced to define it, lest a call to it result in a compiler error (otherwise the derived class is also considered abstract).
Note that destructors should never be pure virtual. The way you have it right now is great; you unconsciously followed the rules I've outlined above.
Some other notes:
Variable length arrays are not legal C++, this is a compiler extension:
int output[T]; // T is read from command line
Use a vector instead:
std::vector<int> output(T);
You have memory leaks as-is. Use a managed pointer like unique_ptr so you don't have to worry about new and delete
I stated that you wanted AddPoint to be pure virtual and I mean it. You code won't compile if that's the first step you take, though. It looks like you merged a base class and a factory into one; split those out.
Putting it all together we can define our new base class as:
template<class T>
class TraversalBase
{
public:
virtual ~TraversalBase(){}
const std::list<int>& GetIndices() const {return indices;}
int GetIndicesSize() const {return indices.size();}
virtual void AddPoint(const T &x, const T &y, int index) = 0;
protected:
std::list<int> indices;
};
The derived class becomes (very little change, also notice the override keyword):
template<class T>
class Traversal : public TraversalBase<T>
{
public:
void AddPoint(const T &x, const T &y, int index) override;
int GetResultXOR() const {return result_xor;}
private:
T coords_s[2];
T coords_e[2];
int result_xor;
void update_result(int index);
T calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2);
};
And our Factory class is much simplified:
template <class T>
struct FactoryTraversal
{
FactoryTraversal(){}
std::unique_ptr<TraversalBase<T>> CreateInstance(const traversal_type &type);
~FactoryTraversal(){}
};
Live Demo (C++11)
Lets say I have this class:
struct testy {
std::array<int, 10> data;
float operator[] (int idx) const { return 1 / data[idx]; }
float &operator[](int idx) { return ??? }
};
What I want to happen is for example, when I write
testy Pineapple;
Pineapple[1] = 0.1;
then what would actually happen is
Pineapple.data[1]= 1 / 0.1;
I started writing the bracket overloads and then realized that the second one that returns by reference cant actually do any logic to transform the data itself so I'm kinda stumped here.
Yes, I know I could just write a setter function but that array will be heavily used by various algorithms and I'd like to make accessing it as convenient as possible from the coding side.
The usual way is to use a proxy for testy elements:
struct testy {
std::array<int, 10> data;
float operator[] (int idx) const { return 1.0 / data[idx]; }
private:
struct element {
int ⪙
element(int &a) : el(a) {}
operator float() const { return 1.0 / el; }
float operator=(float val) const {
el = 1.0/val;
return val; } };
public:
element operator[](int idx) { return element(data[idx]); }
};
Here is a very basic solution with a proxy class:
#include <iostream>
#include <array>
struct testy; // forward declaration
class proxy
{
private:
testy& _t;
int _idx;
public:
proxy(testy& t, int idx): _t(t), _idx(idx) {}
proxy& operator=(double val);
operator double() const; // conversion to double
};
struct testy {
std::array<double, 10> data;
double operator[] (int idx) const { return 1 / data[idx]; }
proxy operator[](int idx) {return proxy(*this, idx);}
};
proxy& proxy::operator=(double val)
{
_t.data[_idx] = 1. / val;
return *this;
}
proxy::operator double() const
{
return _t.data[_idx];
}
int main()
{
testy Pineapple;
Pineapple[1] = 0.1;
std::cout << Pineapple[1] << std::endl;
}
Live on Coliru
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);
};
There is something that is troubling my brain since a moment: I am trying to overload the [] operator based on the return type. Here is what I need to do:
class A {
private:
double* data_;
int N_;
public:
A (N=0):N_(N){
data_ = new double[N];
}
~A {delete[] data_;}
double operator[] (const int i) {
return data_[i];
}
double* operator[] (const int i) {
return &data[i]; // for example; in fact here i need to return some block of data_
}
};
This code won't compile; and that is my problem. Can someone help me to solve this problem?
PS: I know how to overload normal functions on the return type for example:
int foo ();
string foo ();
I used some tricks that I read in this forum. In this way:
struct func {
operator string() { return "1";}
operator int() { return 2; }
};
int main( ) {
int x = func(); // calls int version
string y = func(); // calls string version
double d = func(); // calls int version
cout << func() << endl; // calls int version
func(); // calls neither
}
Thank you.
Two method overloads must have different signatures. The return type is not part of the signature of a method.
You can use the same "trick" that you use for functions, that is use a proxy object with conversion operators:
class A
{
private:
double* data_;
int N_;
public:
A (int N = 0)
: N_(N), data_(new double[N])
{}
~A() { delete[] data_; }
struct proxy
{
int i;
double * data;
operator double() const
{
return data[i];
}
operator double*()
{
return &data[i];
}
operator double const *() const
{
return &data[i];
}
};
proxy operator[] (int const i) {
proxy p { i, data_ };
return p;
}
proxy const operator[] (int const i) const {
proxy p { i, data_ };
return p;
}
};
int main()
{
{
A a(12);
double d = a[0];
double * pd = a[0];
}
{
A const ca(12);
double d = ca[0];
//double * pd = ca[0]; // does not compile thanks to overloads on const
double const * pcd = ca[0];
}
}
However, I would argue that this is a terrible idea. Having your operator[] return either a value or a pointer to this value is guaranteed to confuse the users of your class, in addition to making it impractical to use in expressions where both types are possible. For instance, std::cout << a[0]; would not compile (ambiguous overloads).
Probably you need something like that:
class A {
private:
double* data_;
int N_;
... // other stuff
public:
double operator[] (const int i) const { // note const here
return data_[i];
}
double& operator[] (const int i) { // note reference here
return data_[i];
}
};
also operator should be public to have a sense.