So, I had an exam the other day, and one of the questions was something very similar to this:
We have a class called Square which holds a variable int side. How can we make it possible that cout << static_cast<int>(aSquare) <<endl; would print out the area of aSquare?
Is that even possible?
It's possible to make that work, but not via overloading static_cast<>(). You do so by overloading the typecast operator:
class Square
{
public:
Square(int side) : side(side) {}
operator int() const { return side * side; } // overloaded typecast operator
private:
int side;
};
// ...
// Compiler calls Square::operator int() to convert aSquare into an int
cout << static_cast<int>(aSquare) <<endl;
Beware that overloaded typecast operators more often than not tend to do more harm than good. They make lots of nonsensical implicit cast operations possible. When you read this code snippet below, do you think "a is going to get the area of s"?
Square aSquare;
int a = aSquare; // What the heck does this do?
I certainly don't. This makes way more sense and is much more readable:
Square aSquare;
int a = aSquare.GetArea();
Not to mention that typically you want to be able to access other information about Square, like GetSide() or GetApothem() or GetPerimeter() or whatever. operator int() obviously can return only one int, and you can't have multiple operator int()s as members of a class.
Here's another situation where the operator int() makes code that compiles yet makes no sense whatsoever:
Square s;
if(s > 42) {} // Huh?!
What does it mean for a Square to be greater than 42? It's nonsense, but with the operator int() the code above will compile as Shape is now convertible to an int which can be compared to another int with a value 4.
So don't write typecast operators like that. In fact if you're overloading typecast operators you may want to think twice about what you're doing. There's actually only a few cases where overloading the typecast operator is useful in modern C++ (e.g. the safe bool idiom).
You can overload the cast operator:
struct square {
operator int() const {
return (side * side);
}
int side;
};
The only problem is that it will be used implicitly, and casting doesn't make much sense here. You also can't distinguish between the different types of casts (static_cast, c-style, etc)
This is the preferred way to do things:
struct square {
int get_area() const {
return (side * side);
}
int side;
}
If you must use a cast, use C++11 feature and mark it explicit. This prevents implicit casting mistakes.
You could provide a conversion operator for the Square class:
class Square
{
public:
operator int()
{
return side * side;
}
private:
int side;
};
Related
I find myself in a situation where I'm tempted to put two conversion operators in a single class. Normally I would avoid this like the plague. But with C++ 11 and explicit conversion operators, it seems what I want to achieve is both reasonable and safe. However I need a sanity check.
Consider the following class ("Distance") meant to tie together a distance value with its unit of measurement.
enum class Unit { None = 0, Meter = 1, Foot = 2, }; // None means INVALID
class Distance
{
Unit m_unit;
double m_value;
public:
Distance() : m_unit(Unit::None), m_value(0.f) {} // construct invalid
Distance(Unit u, double, v) : m_unit(u), m_value(v) {}
Unit unit() const { return m_unit; }
// Two functions that I would like to make into cast operators:
double value() const { return m_value; }
bool valid() const { return Unit::None != m_unit; }
// Cast operators I would LIKE to add and use. Implicitly cast to
// double but in "if()" scenarios, cast to bool to check validity
operator double() const { return m_value; }
explicit operator bool() { return valid(); }
};
Since a Distance object is meant to be treated as if it were a double value (most of the time), I considered adding the implicit double cast (above). But in certain contexts, a Distance can be considered "invalid", represented by a unit value of Unit::None. In that case I really like the idea of adding the explicit boolean cast.
The end goal is to be able replace code that currently reads like this:
void doSomething(bool b) {}
void doSomething(double d) {}
void DumpDistance(const Distance& dist)
{
if (dist.valid())
std::cout << dist.value() << std::endl;
doSomething(dist.valid()); // properly calls bool version
doSomething(dist.value()); // properly called double version
}
into this:
void DumpDistance(const Distance& dist)
{
if (dist) // treated as bool (good)
std::cout << dist << std::endl; // treated as double (good)
doSomething(dist); // calls double overload (good)
}
In my testing, it seems the explicit bool operator does the trick. But I'm not sure. It looks like the desired overloads are being called. But I have a built-in aversion to casting operators burned into me in dark old days of the 1990s.
So my question:
Is this really is as safe as it seems? Is there some obvious case I'm missing in which the compiler would complain about an ambiguous conversion or even worse, silently calls one operator when I wanted another?
(To be clear: I'm not asking about the necessity of this nor about its readability. Only about the dangers of compile-time ambiguities or conversions I don't want to happen. I need to solidify the concept of explicit conversion operators in my head. )
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
I was told that you can in fact do MyClass a, b; ... if (a && b) {...} without 1) overloading the && operator 2) overloading the bool operator (ex: class MyClass { ... operator bool(){return boolval; } };)
The solution was to use a pointer-to-member-function. I did not understand how to use this solution. My notes say the below but i couldn't get more then that. Does anyone know how to do this?
the function takes a private nested
struct as a parameter. The reason is
that that type can’t legally be
converted into anything else – it can
never be used in any expression other
than a Boolean context
Note: Typically answers to [homework] questions do not immediately give away the solution. However, according to your question you already know the solution but don't understand it. I'll attempt to explain.
From the information you provided in your question, your instructor was probably talking about some variant of the safe bool idiom:
class MyClass
{
private:
typedef void (MyClass::*SafeBoolType)() const;
void ThisTypeDoesNotSupportComparisons() const {}
public:
operator SafeBoolType() const {
// The actual conditional expression would go where "true" is.
// ____
// | |
return (true) ? &MyClass::ThisTypeDoesNotSupportComparisons : 0;
}
};
int main()
{
MyClass a;
MyClass b;
if(a && b) {} // Compiles.
/* if(a < b) {} */ // Doesn't compile.
}
Here, we provide a type cast operator to a pointer-to-member-function, which can only be used in boolean contexts. This allows the if statement with the logical operator (&&) to compile even without a bool typecast or an && operator overload. It also prevents the if statement with the comparison operator (<) from compiling.
However, I don't understand the part in your notes that mentions "the function takes a private nested struct as a parameter". The safe bool idiom doesn't require that the member function take an unnamed struct. I suggest that you ask your instructor; it is possible that I have completely misunderstood the problem.
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?
I'm looking to add functionality to all the simple types in C++.
I want to write a single templated class that takes as a template parameter the type to be encapsulated and then has all the operators defined so that the encapsulated class works exactly as the simple type it encapsulates.
Something like this:
template <typename _SimpleType_>
class Attribute
{
public:
Attribute(_SimpleType_ value){ m_value = value; }
~Attribute(){}
// Cast
operator _SimpleType_() { return(m_value); }
// Comparisons
bool operator==(const a& other) const { return a == m_value; }
etc...
private:
_SimpleType_ m_value;
}
// Use like:
Attribute<int> i = 20;
while(i)
{
if((i & 0xF) == 0)
{
i >>= 2;
}
i--;
} etc...
The question is I'm sure there are a load of nuances that have to be dealt with and specialised template operators written; so is there anywhere that this has already been done so that I can just use that instead?
Boost is too large and complicated to put in my project but I can look at it for pointers if there is a class like this in there - whats its name if there is?
It's pretty simple, if tedious, - you just have to implement all the operators supported by the standard types and where the cast operator is not sufficient.
I have to ask though, why on earth are you trying to do this?
Here is an example of doing with an automatic typecast to T& (tested with GNU C++ 4.3.2):
#include <iostream>
using namespace std;
template <typename T>
class Attribute {
public:
Attribute(const T &value) { v = value; }
operator T & () { return v; }
private:
T v;
};
int main(int argc, char **argv)
{
Attribute<int> i(0);
i = 3;
i++;
i += 4;
i = i + 5;
i <<= 3;
cout << "i is now " << i << endl;
}
The C++ compiler casts automagically the reference to 'Attribute' to a reference to 'int' using the coercion operator 'operator T & ()'. So when the Attribute class does not provide the '++' operator or anything, the object is typecasted to int & and then the operator is looked up from there. Feel free to experiment.
You can get the implementation of the nonmutating operators for free, just by the conversion to _Simple_type_ (and you would get the assignments and increment/decrement by conversion to _Simple_type_&). Another question is whether this is really a good idea, as it creates conversions both T to Attribute<T> and Attribute<T> to T which causes problems while overloading - but you could fix that by making the constructor of Attribute<T> explicit.
This leaves the assignments and increment/decrement - you would just have to implement those.
Another possibility is using boost::operators - a header only library that facilitates creation of operator overloads based on algebraic rules. eg. you create operator+=, and it will provide you operator+. You create operator< and operator== and it will give you the other relationals etc.
Not to do with your question, but you should be aware that names such as _SimpleType_ (that is, names that begin with an underscore and an uppercase character) are reserved for the C++ compiler and Standard Libarary implementors to use - you are not allowed to use them in your own code.
I'm not sure if boost::ref is what you're looking for.
At any rate, the best thing you'd do is to just write it out by hand -- but this will start becoming a problem if you intend to support pointer and reference semantics.
What you'd also proabably need to do is put it in a namespace and implement the free function operator overloads and rely on ADL for it to get picked up. This will get a little unwieldy though as you implement more and more operators.
I like this form of encapsulation of simple types (original author - Sektor van Skijlen):
template<typename T>
class explicit_t
{
private:
T value;
template<typename V> explicit_t(V t);
public:
operator T&() {return value;}
explicit_t(const T& c) : value(c) {}
};
And the short example:
void fun(explicit_t<int> foo) {}
int main()
{
// fun('a');
// fun(3u);
// fun(3.0);
fun(4);
}
So what do I get? No more unwanted conversions.
You might also want to have a look at something more fancy - typegen.