How can I implement `my_class_instance(a, b) = value` operation - c++

I have a class Flight and I need to implement two operations:
Flight s;
auto value = s(1, 2);
s(3, 4) = value;
I know how to implement first operation:
class Flight
{
public:
int operator()(int a, int b) {
return cache.for(a, b).get();
}
private:
// cache
}
But I don't know implement second operation. Something like this:
void operator()=(int a, int b, int value) {
cache.for(a, b).set(value);
}
Now I have an error operation is not accessible for expression like s(3, 4) = value;.
How can I implement this operation?

There is no ()= operator. It is two separate operators - operator(), and then operator= on the return value of operator().
Since you want to use separate get() and set() methods inside the cache, you will have to make your Flight::operator() return a helper proxy, and then you can implement proxy::operator int to call the get() method and proxy::operator= to call the set() method, eg:
class Flight
{
public:
class Proxy
{
private:
Flight &f;
int a, b;
public:
Proxy(Flight &f, int a, int b) : f(f), a(a), b(b) {}
operator int() {
return f.cache.For(a, b).get();
};
Proxy& operator=(int value) {
f.cache.For(a, b).set(value);
return *this;
}
};
friend class Proxy;
Proxy operator()(int a, int b) {
return Proxy{*this, a, b};
}
private:
// cache
};
Then your example will work as you want:
Flight s;
int value = s(1, 2); // <-- important - int, not auto!
s(3, 4) = value;
Live Demo

Related

How to code operation overload so it operates to a specific class member such as A<<{{1,2,3},{5,6,7}} in c++?

You can redefine operator << in class by overload it.
However, how do you code it so that it would operates specific to a certain class member?
for example
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a << 1; // sets class member a to value 1;
}
I want a operator defined in Class C that operates specifically to class member a.
a pesudo-code would be
class C
{
int a;
double b;
void operator << (istream & fin)
{
... fin.get()... some code
}
}
Stating the obvious for a moment, assuming the variable is public, you'd use:
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a = 1; // sets class member a to value 1;
}
The << and >> operators are bit shifts, which have their own meaning. Overloading those for your own purpose is probably a bad idea.
The C++ way of doing things is to avoid setting member variables externally where possible (e.g. using RAII approaches, to set data at initialisation)....
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
private:
int a;
double b;
};
.... Or by adding a setter method if you really need it, e.g.
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
void setA(int v) { a = v; }
void setB(double v) { b = v; }
private:
int a;
double b;
};
You could in theory generate a new type, and overload the operators for that type, but it's not something I'd recommend (because changing the meaning of an operator is almost always a bad idea)
struct MyIntType {
int i;
// overload cast operator
operator int () {
return i;
}
// assign
MyIntType& operator = (const int& v) {
i = v;
return *this;
}
// not recommended :(
MyIntType& operator << (const int& v) {
i = v;
return *this;
}
};
class C
{
public:
MyIntType a;
double b;
};
void main ()
{
C c;
c.a << 1;
}
Having read your comment above, it sounds like you want to do this:
class C
{
public:
// I'm still not recommending this :(
C& operator << (const int& v) {
a = v;
return *this;
}
private:
int a;
double b;
};
void main ()
{
C c;
c << 1; //< now sets c.a
}

User defined conversion assigned to const ref variable via temporary object

The code below is a simplified version of the actual problem I am facing.
Assume I do not have permission to modify class A (as it is external library), and its already widely used in my existing code base.
The const & assignment from a temporary object (direct constructor) which also return a const & member variable via implicit conversion is not valid in this case.
How do I prevent or make it legal in this case so that the caller gets the correct A value?
class A
{
public:
A() { }
A(int _r, int _g, int _b)
: r(_r), g(_g), b(_b)
{
}
~A(){ }
int GetR() const { return r; }
int GetG() const { return g; }
int GetB() const { return b; }
private:
int r = 0;
int g = 0;
int b = 0;
};
class Foo
{
public:
Foo() : Foo(A()) {}
Foo(int _r, int _g, int _b) : a(A(_r, _g, _b)) {}
explicit Foo(const A& _a) : a(_a) {}
Foo& operator=(const A& a)
{
*this = Foo(a);
return *this;
}
operator A() const { return a; }
operator const A&() const { return a; }
private:
A a;
};
int main()
{
const A& a = Foo(200, 100, 300);
std::cout << a.GetR() << a.GetG() << a.GetB() << endl; // I may not get 200 100 300 here as Foo is already out of scope
return 0;
}
Motivation
Some background on why I am implementing a class as above. The actual purpose of class Foo is to contain 2 different objects, which actually has the same purpose, just different way of storing data internally. For example, let's say class A and class B, which stores RGB value of color in int and floating (normalized) respectively. And as mentioned above, I do not have permission to modify class A, and its already widely used in my code base.
There are tons of function in my code base which takes in const A& and const B& as a function param. So I am trying to unify this 2 classes for a particular case, where I can just pass in Foo in those places and it will work as expected.
You can apply ref-qualified member functions (since C++11), i.e. mark the conversion operator with lvalue-reference, to prevent it being called on temporaries (rvalues).
class Foo
{
public:
... ...
operator A() const { return a; }
operator const A&() const & { return a; }
operator const A&() && = delete;
... ...
};
Then
const A& a = Foo(200, 100, 300); // invalid; invokes deleted operator
const A& a = static_cast<A>(Foo(200, 100, 300)); // fine; invokes operator A()

c++ create a class, call its funcion and push back to vector in one statement

I have a class MyClass and another class that holds an array of MyClass, as follows:
class MyClass {
int a;
float b;
void SetInt(int value)
{
a = value;
}
void SetFloat(float value)
{
b = value;
}
}
class MyClassArray {
std::vector<MyClass> classList;
}
What is the easier way to create a new MyClass, insert an object in MyClassArray and call the methods to store value on it ?
Can I just create a temporary MyClass and insert it on the vector, calling the function in one statement ? Like:
classList.push_back(MyClass().SetInt(21));
classList.push_back(MyClass().SetFloat(1.23));
Is that valid ?
BTW: I need in vector a one object MyClass with 21 set on a and another one with 1.23 set on b, that´s why I´m not using initializers for a and b.
you can use chaining :
class MyClass {
int a;
float b;
public:
MyClass& Set(int value) { a = value; return *this; }
MyClass& Set(float value) { b = value; return *this; }
};
this enables thing like:
MyClass a;
a.Set(1).Set(1.5f);
and also:
vector<MyClass> vec;
vec.push_back(MyClass{}.Set(3));
Use your constructor
class MyClass {
int a;
float b;
}
class MyClassArray {
std::vector<MyClass> classList;
classList.push_back(MyClass(21,1.23));
}
You can use constructors for this. If you overload the constructor to take either an int or a float you would be able to set the value for both of the situations that you outlined.
class MyClass
{
int a;
float b;
MyClass(int i) : a(i) { }
MyClass(float f) : b(f) { }
}
this way you could add objects to the vector by doing this:
std::vector<MyClass> classList;
classList.push_back(MyClass(21));
and by doing this:
classList.push_back(MyClass(1.23));
If you really need to call a separate method you could do it like this:
class MyClass {
int a;
float b;
MyClass& SetInt(int value)
{
a = value;
return *this;
}
MyClass& SetFloat(float value)
{
b = value;
return *this;
}
}
Which will return a reference to the class. It is far better to do it using constructors though.

Compare field in derived template class

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.

How to get rid of the ugly record

class c {
private:
int n[10];
public:
c();
~c();
int operator()(int i) { return n[i];};
};
class cc {
private:
public:
c *mass;
cc();
~cc();
c& operator*() const {return *mass;};
};
int somfunc() {
c *c1 = new c();
cc * cc1 = new cc();
(*cc1->mass)(1);
delete c1;
}
I've got a pointer into class cc to class c.
Is there any way to get rid of record like this:
(*cc1->mass)(1);
and write somethink like that:
cc1->mass(1);
is it impossible?
When I saw the tags "c++" and "operator overloading", my mind alarm turns ON.
C++ operator overloading is complex, and some operators like "()" or "->" make it more difficult.
I suggest, before overloading operators, making either a global function or method with the same purpouse, test it works, and later replace it with the operator.
Global friend function example:
class c {
private:
int n[10];
public:
c();
~c();
// int operator()(int i) { return n[i]; }
// there is a friend global function, that when receives a "c" object,
// as a parameter, or declares a "c" object, as a local variable,
// this function, will have access to the "public" members of "c" objects,
// the "thisref" will be removed, when turned into a method
friend int c_subscript(c thisref, int i) ;
};
int c_subscript(c* thisref, int i)
{
return c->n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c_subscript(objC, 3);
// do something with "x"
return 0;
} // int main(...)
Local function ( "method" ) example:
class c {
private:
int n[10];
public:
c();
~c();
// int operator()(int i) { return n[i]; }
int subscript(int i) ;
};
int c::subscript(int i)
{
return this.n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c->subscript(objC, 3);
// do something with "x"
return 0;
} // int main(...)
And, finally use the overloaded operator:
class c {
private:
int n[10];
public:
c();
~c();
int subscript(int i) ;
int operator()(int i) { return this.subscript(i); }
};
int c::subscript(int i)
{
return this.n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c->subscript(3);
// do something with "x"
int x = c(3);
// do something with "x"
return 0;
} // int main(...)
Note that in the final example, I keep the method with a unique identifier.
Cheers.
Could always do this:
class cc {
private:
c *_mass;
public:
c& mass() const {return *_mass;};
};
Now..
cc1->mass()(1);
If mass were an object, not a pointer, you could use the syntax you want:
class cc {
private:
public:
c mass;
cc();
~cc();
const c& operator*() const {return mass;};
};
…
cc1->mass(1);
You can with
(*(*cc1))(1)
because operator() is applied to an object, not a pointer.
You can use
(**cc1)(1);
Or
cc1->mass->operator()(1);