Suppose I have a class called Complex with 2 parameters real and imag. I want to overload the =(assignment) operator so that I could copy the value from the real parameter and assign it to an int.
If my main would look something like;
Complex z(1, 2);
int a = z;
I want a to be equal to 1.
How can I implement this function/method?
Use cast operator:
//Declaraion
class Complex {
operator int();
}
//Definition
Complex::operator int() {
return real_number;
}
Cast operator can implicitly convert a class instance to a certain type that is defined. It is a handy tool, but sometimes can be dangerous and vulnerable, and hard to debug.
When you define the assignment operator you are instructing the compiler on what to do when a value of possibly a different type is assigned to and instance of your class.
In this case instead you want to define what to do when an instance of your class is assigned to a variable of a different non-class type and this is not possible however. In other words it's the receiving instance that defines what to do in case of an assignment and you can customize this only for class types.
Something quite similar is instead to define how an instance of your class should be convertible to another type, e.g. how to convert a complex to an integer, and this conversion will be used also in case of assignment:
struct complex {
double real, imag;
...
operator int () const { return int(real); }
};
It isn't ideal to have code that reads as an assignment of types from different equivalence classes. It is correct that one should use casting instead, but the casting must be made explicit in C++11:
struct Complex {
double r, i;
...
explicit operator int () const { return int(r); }
};
Complex c = { 1.1, 2.2 };
float a = c; // fails with explicit
float a = (float)c; // fails with explicit
int a = c; // fails with explicit
int a = (int)c; // compiles with explicit
Do you really need to define a class for complex? It's part of standard library
Even you can see <complex> (#include <complex>) to find the operators and definitions overloaded
See more here
Related
I have a particular class for which I want to write a typecast operator, but I can't modify the class code directly.
Example:
class MyClass; // not modifyable
class MyClass
{
// can't do this
operator AnotherType () const
{
AnotherType t;
t.setSomething();
return t;
}
}
MyClass m;
static_cast<AnotherType> m; // want to be able to do this
Is it possible to express as an external function something which will be called by static_cast?
This was my attempt, which did not work, and I did not expect to work.
operator AnotherType(MyClass m)
{
AnotherType t;
t.setSomething();
return t;
}
The error produced by the compiler indicates that static_cast is looking for a constructor for AnotherType which takes a MyClass as an argument. This indicates a possible alternative, which would be to write a conversion constructor. This will only work if the type to be cast to is modifyable.
It would also be possible to write an external function which does the conversion without the use of a conversion constructor. But this will not be called by static_cast.
eg:
AnotherType convertFunction(MyClass) {...}
There is an alternative solution which it to use the Adapter pattern, and write a type-conversion operator in the Adapter class. It might be this is the only solution in my case.
You can't have A a; static_cast<B>(a); work if you can't change A nor B.
You can have A a; B b = static_cast<Something>(a); work, if you can define Something.
See it on coliru
Is using the cast constructor bad?
Otherweise why a code quality checker (cppcheck in my case) would constantly suggest to add explicit before single parameter constructors?
What if I want to do
class MyClass {
A(int) {}
};
A a = 1;
If I follow the "suggestions" and write
class MyClass {
explicit A(int) {}
};
A a = 1;
would throw an error, but if I use the first I'll have a warning that i've to document to pass the code reviews.
C++ Core Guidelines
C.46: By default, declare single-argument constructors explicit
Reason
To avoid unintended conversions.
Example, bad
class String {
public:
String(int); // BAD
// ...
};
String s = 10; // surprise: string of size 10
Exception
If you really want an implicit conversion from the constructor
argument type to the class type, don't use explicit:
class Complex {
public:
Complex(double d); // OK: we want a conversion from d to {d, 0}
// ...
};
Complex z = 10.7; // unsurprising conversion
See also: Discussion of implicit conversions
Such implicit class type conversion can be used easily without intention. With this converting constructor every function or member function which accepts MyClass as argument will accept also int. Therefore every int passed to such a function will be converted to a temporary MyClass which will be discarded after the function has finished. Probably not what you want.
I have a class of complex numbers, loaded the +, -, *, /,=,!= operators both with complex and double types on both ways but when I write the code complex z = 1, the compilers gives me an error saying that there are no variable conversion from int to complex. Although, it accepts the code
complex z;
z = 1;
and everything works fine. How can I fix this error?
The line complex z = 1 does Copy Initialization. You'll need an appropriate constructor:
complex::complex(int i) // or double or whatever is convertible to int by
{ // implicit conversion
// your code
}
This is different than
complex z;
z = 1;
which is assignment (to a previously default constructed object) that requires an assignment operator.
You may want add a constructor which accepts a double:
class complex
{
public:
complex(double d) : _real(d), _imag(0) { }
...
};
Be careful, though: this will make it possibly to pass an int wherever a complex is expected, because your constructor will perform an implicit conversion.
You need to write an appropriate constructor.
class complex {
public:
complex(double x) {
// ...
}
// ...
};
You need a constructor that takes a double.
class complex
{
public:
complex( double d );
};
I read following code from somewhere:
template<class T> class A {
T a;
public:
A(T x):a(x) {}
operator T() const {return a;} // what is point here?
};
int _tmain(int argc, _TCHAR* argv[])
{
A<int> a = A<int>(5);
int n = a;
cout << n;
return 0;
}
What does below line mean?
operator T() const {return a;}
operator T() const {return a;}
This is the typecast operator. It'll implicitly convert the class instance to T. In the example code you've posted this conversion is being performed at the line
int n = a;
It means if you want to convert an instance into a T you can use this operator, which here returns a copy of the private member.
In your example code that is how you can assign a, which is of type A<int> to an int directly. Try removing the operator T() and see how that fails to compile, with an error about assigining A<T> to an int.
With the non explicit constructor (the opposite of marking a constructor explicit) there too it makes this type behave a lot like the template type itself in a number of circumstances. In effect you've wrapped a T inside another class that behaves like a T when it needs to. You could extend this to do other, more useful things like monitoring/logging/restricting the use of real instances by hiding them behind something which controlled them.
Also notice how you can change A<int> a = A<int>(5); to simply A<int> a = 5; because of the implicit constructor.
It's basically making a functor - which is an object with function semantics. That means you can call the object just like a function as a replacement in places where you may have used a function - its a generic programming concept.
It's beneficial because you can have multiple instances of that function-object (functor) and they can each maintain their own state, where as if you had a straight-up function then it could only maintain state via static variables, and it would thus not be re-entrant (you only ever get one instance of a static variable).
Functors are heavily used in STL algorithms as an extra optional parameter.
I want to create a collection of classes that behave like math vectors, so that multiplying an object by a scalar multiplies each field by that ammount, etc. The thing is that I want the fields to have actual names, instead of being treated as an index.
My original idea to implement this was creating a base class Rn with the overloads and then create derived classes with the pretty names. Something like this:
#include <iostream>
#include <algorithm>
using namespace std;
template<int N, class X=double>
struct Base{
X xs[N];
Base(){};
Base(X *data){
copy(data, data+N, xs);
}
Base operator*= (double d){
for(int i=0; i<N; i++){
xs[i] *= d;
}
return *this;
}
Base operator* (double d){
Base answer = *this;
answer *= d;
return answer;
}
//also operators for +=, +, multiplication from left, maybe [] too
};
struct Derived : public Base<2>{
Derived(double a, double b){
foo() = a;
bar() = b;
}
double &foo(){ return xs[0]; }
double &bar(){ return xs[1]; }
};
int main()
{
//this is OK:
double data[2] = {0.0, 2.0};
Base<2> b(data);
b = b*17.0;
cout << b.xs[0] << endl;
//I can't do this:
Derived x(0.0, 2.0);
x = x*17.0;
cout << x.foo() << endl;
return 0;
}
I get a compiler error whenever I try to use of of the operators that requires copying.
gcc gave me the following compiler error:
teste.cpp: In function ‘int main()’:
teste.cpp:52: error: no match for ‘operator=’ in ‘x = x.Derived::<anonymous>.Base<N, X>::operator* [with int N = 2, X = double](1.7e+1)’
teste.cpp:31: note: candidates are: Derived& Derived::operator=(const Derived&)
I think the problem is that the overloading functions deal with Base objects that can't be converted to Derived ones, so I can't use them in the derived class. However, I can't come up with a solution. Is there a way around this or should I use a totally different approach?
Bonus question: is there some way that I can use std::valarray to keep from having to type lots and lots of operator overloads?
Your Base operators (* in this case) can accept Derived object, but they return a Base, which can't be used as a right-hand operand in Derived default assignment operator. Easiest way to fix this is just add an assignment operator to Derive that will take a Base:
Derived& operator= (const Base<2>& other)
You will have to add it to any derived class, but the implementation is rather straightforward (you can have a void CopyOtherBase function in Base that will do the copy, and have all operator= call it and return *this).
I'll only address the technical difficulty, not whether this is a good idea or not.
The problem is that the result of operator* of Derived is a Base, and operator= of Derived (which is a default operator=) doesn't know how to "eat" a Base.
A simple solution is to create a constructor of Derived that gets a Base, and does whatever is needed to initialize itself correctly. This would allow an on-the-fly conversion of a Base to a Derived - and would work for all other operators of Derived that expect a Base.
Something along the lines of -
Derived(const Base<2>& B) : Base<2>( B )
{
}
I think you're going to be much better off using an enum or static constants to name your fields
e.g., static const int FIELD_NAME = 0;
Static const int FIELD_NAME2 = 1;
than doing this as different types (templates). Then you can go for std::valarray or boost::ublas::vector/matrix types to leverage existing code & get quality performance vector operations to boot.
Template metaprogramming had an interesting idea on solving just this sort of issue with math vectors, but perhaps doesn't solve your issue of naming the parts.
David Abrahams, Aleksey Gurtovoy: C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond, Addison-Wesley, ISBN 0-321-22725-5
According to MSDN,
All overloaded operators except
assignment (operator=) are inherited
by derived classes.
Could this be your problem?