C++11 overload of `M operator+(M&&,M&&)` - operator-overloading

Update: clarification, more clear focus and shortened example:
Can I circumvent the M op+(M&&,M&&) overload? Assuming, I want good handling of RValues? I guess the other three overloads are required.
Reason why I have the (&&,&&) overload in the first place:
Normally I would not provide M op+(&&,&&), but I seem to need it: When providing overloads for (&&,&) and (&,&&) the compiler gets into an ambiguity. Is there a better way to resolve it then to add another implementation variant?
You can also look at the complete code.
struct Matrix {
...
// 2ary ops
friend Matrix operator+(const Matrix &a, Matrix &&b ) { b+=a; return move(b); }
friend Matrix operator+(Matrix &&a, const Matrix &b) { a+=b; return move(a); }
friend Matrix operator+(const Matrix &a, Matrix v) { v+=a; return v; }
friend Matrix operator+(Matrix &&a, Matrix &&b) { a+=b; return move(a); }
// ... same for operator*
// ... assume impl of operator+=,*= and move semantics
};
int main() {
Matrix a{2},b{3},c{4},d{5};
Matrix x = a*b + c*d; // reuires &&,&& overload
std::cout << x << std::endl;
}

The following helper function returns the first value if it an rvalue, otherwise the second value (which may be an rvalue, but may not be).
template <class T1, class T2>
typename std::enable_if<! std::is_reference<T1>::value, T1&&>::type
get_rvalue(T1&& t1, T2&& t2) { return std::forward<T1>(t1); }
template <class T1, class T2>
typename std::enable_if<std::is_reference<T1>::value, T2&&>::type
get_rvalue(T1&& t1, T2&& t2) { return std::forward<T2>(t2); }
The following helper function returns the other value not returned above.
template <class T1, class T2>
typename std::enable_if<! std::is_reference<T1>::value, T1&&>::type
get_non_rvalue(T1&& t1, T2&& t2) { return std::forward<T2>(t2); }
template <class T1, class T2>
typename std::enable_if<std::is_reference<T1>::value, T2&&>::type
get_non_rvalue(T1&& t1, T2&& t2) { return std::forward<T1>(t1); }
This just compares if two types are the same, ignoring references and const.
template <class T1, class T2>
struct is_same_decay : public std::is_same<
typename std::decay<T1>::type,
typename std::decay<T2>::type
> {};
Then we can do just one overload for each function (using templates) like the following:
// 2ary ops
template <class M1, class M2>
friend typename std::enable_if<
is_same_decay<M1, Matrix>::value &&
is_same_decay<M2, Matrix>::value,
Matrix>::type
operator+(M1&& a, M2&& b)
{
Matrix x = get_rvalue(std::forward<M1>(a), std::forward<M2>(b));
x += get_non_rvalue(std::forward<M1>(a), std::forward<M2>(b));
return x;
}
template <class M1, class M2>
friend typename std::enable_if<
is_same_decay<M1, Matrix>::value &&
is_same_decay<M2, Matrix>::value,
Matrix>::type
operator*(M1&& a, M2&& b)
{
Matrix x = get_rvalue(std::forward<M1>(a), std::forward<M1>(b));
x *= get_non_rvalue(std::forward<M1>(a), std::forward<M1>(b));
return x;
}
Note above, if either M1 or M2 is an rvalue, get_rvalue(a, b) will return an rvalue, hence in this case Matrix x will be populated by a move, not a copy. Named return value optimisation will probably ensure that there is no copy (or even move) required into the return value, as x will be constructed in the place of the return value.
Full code is here.

Matrix& operator=(Matrix&& o) { swap(*this,o); };
First, your Matrix class has nothing (as of yet) that needs moving, so you shouldn't bother writing one. Like a copy constructor, only define one if you need to. Let the compiler take care of it unless you have a legitimate need (like storing a naked pointer).
Second, that function of yours doesn't move; it swaps. An "idiomatic" swap-based move involves a temporary, like this:
Matrix temp;
swap(o, temp);
swap(temp, *this);
friend Matrix operator+(const Matrix &a, Matrix &&b ) { b+=a; return move(b); }
friend Matrix operator+(Matrix &&a, const Matrix &b) { a+=b; return move(a); }
friend Matrix operator+(const Matrix &a, Matrix v) { v+=a; return v; }
friend Matrix operator+(Matrix &&a, Matrix &&b) { a+=b; return move(a); }
What are you trying to accomplish here? Again, your object doesn't have anything that gets moved; there's no point in doing this. Just because you could move something, doesn't mean you should. If you really wanted to cut down on code duplication, you would do things normally:
friend Matrix operator+(const Matrix &a, const Matrix &b) { Matrix temp = a + b; return temp; }

Related

Invalid initialization of reference type 'Class&' from expression of type 'Class'

Ok guys , so I have a list of objects and I want to sort my list by a boolean function I created .
Function ->
bool funct(Student &s1,Student &s2)
{
return s1.calculMedie()<s2.calculMedie();
}
I got this list:
list<Student*> list;
list.push_back(sx[0]);
list.push_back(sx[1]);
list.push_back(sx[2]);
sx is comming from this declaration-> Student **sx=new Student*[3];
I created 3 objects of the type class Student.
I want to sort them by 'calculMedie()' which is a function that returns their average grade.
double Student::calculMedie()
{
int nr=0;
double s=0;
for(auto i : note)
{
nr++;
s=s+i;
}
return s/nr;}
^ thats how it looks.
And when I tried to do a list.sort(list.begin(),list.end(),funct) it gets me this error : " Invalid initialization of reference type 'Class&' from expression of type 'Class'"
It looks like you mixed std::sort algorithm with list<T>::sort method. List can be sorted only by using its sort method.
There are two overloads of list::sort:
void sort();
template< class Compare >
void sort( Compare comp ); // [2]
if you want to sort by comparator, write as follows:
list<Student*> list;
list.sort (funct);
because list stores pointers to Student, you need to modify signature of funct function, it must takes pointers not references:
bool funct(Student* s1,Student* s2)
{
return s1->calculMedie()<s2->calculMedie();
}
good practice is to pass s1,s2 as pointers to const object, when you change s1,s2 to be const Student* s1, const Student* s2 you need also to make calculMedie as const member function.

How do I write this function of this class?

I'm a beginner in C++ so I'm not sure how to make the question more detail. I'm sorry.
So my professor gave me this header file and told me to write the function definition:
class Move
{ private:
double x;
double y;
public:
Move( double a = 0, double b = 0 ); // sets x_, y_ to a, b
void showmove(Move number) const; // shows current x_, y_ values
// add : Move --> Move
// to add x_ of input object to x_ of invoking object to get new x_,
// to add y_ of input object to y_ of invoking object to get new y_,
// to create new object initialized to new values and return it
Move add( const Move &m ) const;
void reset( double a = 0, double b = 0 ); // resets x, y to a, b
};
I don't understand the function Move add( const Move &m ) const;. Usually an add function look like this int add( int a, int b) . So combine 2 inputs together to make 1 output. But the function Move add only has one input. I don't know how to write a definition for it. I asked my friends and we come up with something like A.add(B), but I'm not sure if it makes any sense.
Thank you for reading and sorry for my English
The definition should be
Move add(const Move& m) {
return Move(this->x+m.x, this->y+m.y);
}
It wants you to use m's attributes to get the results directly with only one parameter (reference to a Move object) instead of two (coordinates) .
Indeed, to invoke this method :
Move A/*sthg*/;
Move B/*sthg*/;
Move C = A.add(B);

Shall I build a destructor in this classes?

I am currently working on building an ABM model using C++.
I have classes that have the need to interact with each other, because e.g. class B needs to examine values in class A and return some evaluation on it, which then class C might want to read. Classes need not to change other classes values, only to read from them.
Class B in my current implementation has a po
inter to a vector containing all members of Class A. The pointer is there for two order of reason: it makes easier to initialize the vector, and the vector is left in the scope of main so that I can access and loop over it, calling the members of class A for each agent.
My MCVE:
#include <iostream>
#include <vector>
using namespace std;
class A; // Forward declaration
class B{
int id,
some_value;
vector<A> * A_vec;
public:
// Overloaded constructor
B(int ID, vector<A> & PTR)
{
A_vec = & PTR;
id = ID;
some_value = 0;
};
// Copy Constructor
B( const B& that ):
id(that.id),
some_value(that.some_value)
{
// Pointer ??
};
// Non-default destructor -> uncomment leads to seg_fault
/*
~B(){ delete [] A_vec;};
*/
// Assignment operator
B& operator=(const B& that)
{
id = that.id;
some_value = that.some_value;
// Pointer ??
return *this;
};
//Methods to update different variables go here ..
void do_stuff();
};
class A{
B & class2_ref;
vector<double> o;
public:
int stuff;
// Overloaded constructor
A(int STUFF, B & REF, vector<double> O):
class2_ref(REF),
o(O)
{
stuff = STUFF;
};
// Methods to update different variables go here ..
};
void B::do_stuff()
{
int L = A_vec->size();
for(int l = 0; l<L; l++) some_value += (*A_vec)[l].stuff; // Perform some operation
};
int main(){
int I = 5; // Number of objects of A
vector<double> O(12,2); // Some numbers in here
B b(0,A_vec);
for(int i = 0; i< I; i++)
{
A a(i,b,O);
A_vec.push_back(a);
}
b.do_stuff();
cout<< "Debugging MCVE" << endl;
return 0;
}
My question then is:
Should I implement the destructor/copy constructor/assignment operator in class B? What about class A ? If so, can you please point me to the correct syntax(for the destructor the one above in comments leads to seg fault).
My understanding is that this might be one of the case in which I am happy with a "shallow" destruction of the pointer, because both class B and vector<A> will go out of scope at the return statement. class B owns the pointer, which gets destructed when it is due, and the same for vector.
But then, what about the other member from the rule of three?
There is only one object of class B planned, but I might (small chance) want to generalize later on.
if a class have a pointer type, you should implement a destructor, and i would suggest implementing a copy and an assignment operator as well, else you will be dealing with the same object from 2 different places, which could cause you some errors, for example -
void someFunction(B &b)
{
B a = b;
}
B b(0,A_vec);
someFunction(b); //After finishing someFunction, it will try to delete the vector from a , but it is the same vector you used in b.
b.do_stuff(); // Would cause a seg error
And for the destructor syntax, just delete the vector, not its content, it will use the vector default destrctor on the content:
delete A_vec
just make sure you dont use it if its not initialized, i would suggest just building a empty vector on each ctor of the class, that way you wont get a seg fault and you can use delete.

Inheritance with templates

#include<iostream>
using namespace std;
class C
{
public:
C (){};
virtual void nothing()=0;
virtual ~C (){};
};
class A : public C
{
public:
A (){};
virtual void nothing(){};
};
class B:public A
{
public:
B(){};
void nothing(){};
};
template <class T>
void hi(T){
cout << " i am something\n";
}
template <>
void hi<A>(A)
{
cout << " I am A\n";
}
template <>
void hi<B>(B)
{
cout << " I am B\n";
}
int main ( )
{
C *array [] = {new A,new B};
hi (*array [0]);
hi (*array [1]);
delete array [0];
delete array [1];
return 0;
}
Out:
i am something
I am something
Currently I am writing a program that has to deal with
Inherited types and specialised templates. In the example above I would l would like to see
I am A
I am B
Is there a way to properly invoke the functions corresponding to the objects although I am handling a base class array? I am not sure if type checking and conversion via dynamic_cast is the most elegant solution. Note that this is just an excerpt from a larger program.
Thank you in advance
In the main routine, the three lines shown below create an array of C*.
So any element of that array is treated as a C* regardless of
what the actual type of the element is.
That is, when you pass *array [0] to the function hi(),
the function that gets called is hi(C) which resolves to
the generic hi function, not either of the specialized functions.
C *array [] = {new A,new B};
hi (*array [0]);
hi (*array [1]);
In order to make hi<A> be invoked, you either have to store the pointer
to the new object in a variable of type A* or you need to cast the
C* to an A*.
In a case like this, a virtual function of C, overridden in A and B,
may serve the purpose better.

Accessing to outer class

I am reading "The D Programming Language" book at the moment. It is telling about the inner classes.
class Outer{
int x;
this(){
x = 99;
new Inner;
}
class Inner{
int x;
this(){
x = 5;
writeln( "Inner x = ", x, "; Outer x = ", this.outer.x );
}
}
}
As the book tells, to be able to access the class Outer's x, I need to use this.outer.x. But one confusing thing is the name of class "Outer" turns into lower case "outer". With normal class name "Outer", compiler gives error message. It is like compiler decides what you need to use as name and forces to use what name it generates.
My problem is, when I rename the class "Outer" to "bLaH", now I am not able to outer class any more.
class bLaH{
int x;
this(){
x = 99;
new Inner;
}
class Inner{
int x;
this(){
x = 5;
writeln( "Inner x = ", x, "; Outer x = ", this.bLaH.x );
}
}
}
It is not obvious what name to use while accessing to outer class. The first letter is lower case now, but compiler says "test1.bLaH" is not defined. (File name is test1.d)
If I convert "this.bLaH" to "this.blah" by thinking that maybe compiler converts outer class' name to all lower case, this time, compiler says "undefined variable 'blah'".
Is there a design error in the language about this? As a programmer, I don't like this type of name conversion done by compiler.
I am on Windows XP, DMD version is 2.060.
outer is a keyword. It’s like super or whatever. A class is always nested in only one class, so the outer keyword refers to that class.
http://dlang.org/class.html#nested
Here you can find that outer is actually a property.