Operator overloading "operator T * ()" produces a comparison operator? - c++

class Test
{
public:
operator Test * () { return NULL; };
};
int main()
{
Test test;
if (test == NULL)
printf("Wtf happened here?\n");
return 0;
}
How is it that this code compiles? How did Test get a comparison operator? Is there some implicit casting going around? What does that overloaded operator even mean (and do)?

The overloaded operator adds a conversion from Test to Test *. Since there is no comparision operator defined that takes Test and NULL as arguments, any conversion operators that exists are tried. operator Test * returns a type which is comparable with NULL, so it is used.

Yes, you've added an implicit conversion to T*, so the compiler will use it to compare against NULL.
A few other things to note:
NULL is shorthand for 0, so this means that comparison against 0 will be allowed. (This isn't true for other integer values, however. 0 is special.)
Your type also can be implicitly used in boolean contexts. That is, this is legal:
Test test;
if (test)
{
// ...
}
C++0x allows you to specify an explicit keyword for conversion operators to disallow this sort of thing.
Implicit conversion to pointer types is often pretty dubious. In addition to the pitfalls of the conversion happening in unexpected cases, it can allow dangerous situations if the object owns the returned pointer. For example, consider a string class that allowed implicit conversion to const char*:
BadString ReturnAString();
int main()
{
const char* s = ReturnAString();
// Uh-oh. s is now pointing to freed memory.
// ...
}

+1 for Baffe's response. If you're looking to somehow expose some instance of a wrapped object via * then perhaps you should overload -> instead of overloading *.
class Bar
{
public:
void Baz() { ... }
}
class Foo
{
private:
Bar* _bar;
public:
Bar* operator -> () { return _bar; }
}
// call like this:
Foo f;
f->Baz();
Just a thought.

You have not defined your own comparison thus he compiler has done one for you. you have however tried to overload the dereference operator... which I can't see why.
you want to define your operator== function
read this

Related

C++: unusual operator overloading

What an operator is overloaded here?
operator T * ()
I know that the operator method has the following structure:
type operator operator-symbol ( parameter-list )
Assume we have the following code
template<typename T> class SmartPtr
{
public:
SmartPtr(T* data): member(data) {}
T* member;
T& operator * () { return *member; } //usage: *TObj
T*& operator () () { return member; } //usage: TObj()
operator T * () { return member; } //usage: ???
};
No compilation errors if you try it on the ideone. So what is going on here?
ADD: Am I right that static_cast<T*>(TObj) makes a call of the operator T *? I've tried it here.
That's a conversion operator, which allows the class to be converted to T*. Usage:
T * p = TObj;
It's probably a bad idea for a smart pointer to provide this, as it makes it easy to accidentally get a non-smart pointer. Standard smart pointers provide explicit conversion via a get() function instead, to prevent accidental conversions.
This operator is invoked when a SmartPtr object appears in an expression, but the compiler has no functions available to resolve the usage made thereof: if it's legal to use a T* where the SmartPtr appears, the operator T*() function is called to generate one. This means my_smartptr->my_T_member can work, as can f(T*); f(my_smart_ptr_to_T);. Similarly, iostreams have an operator bool() in C++11 (operator void*() in C++03 for reasons too tedious to bother with). It's kind of the opposite of an implicit constructor from a single parameter, where should the compiler not find a valid match using the parameter, it may try to construct an object using that parameter to use instead.
operator T * () { return member; }
it is a so-called conversion operator. It converts an object of type SmartPtr to type T *. Moreover it is an implicit conversion opertaor. So when the compiler awaits an object of type T * you can use instead an object of type SmartPtr.
You could make this conversion operator explicit if you would add keyword explicit. For example
explicit operator T * () { return member; }

Can any class object be passed as test expression for any test expression such as if, while like ifstream object.

In C++, can I use my objects as test expression like ifstream objects. If not, why?
e.g.
ifstream ifs ("myfile.txt");
while( ifs ){
//read and process data..
}
I have a class, which operator do I need to overload to let compiler allow my object to be passed as test expression?
e.g.
MyClass obj1;
if( obj1 ){
//do something..
}
while( obj1 ){
//do something repeatedly..
}
Both should be valid expressions.
You have to implement a bool overload in your class. Something like this:
class myClass {
public:
explicit operator bool() const { return condition; }
};
It will work both in if and while statements. However, if your compiler does not support C++11 you can't use the explicit keyword in this overload.
There are several options you have. Probably best one is to overload the operator bool(). Like so:
class A{
public:
operator bool()
{
return flag;
}
private:
bool flag;
};
EDIT: as pointed out in the comments if you use C++11 it is better to make the operator explicit by adding the explicit keyword to the front. Otherwise probably it is better to use the operator void*()
There are a number of options.
You don’t have to implement an operator bool overload in your class.
And it’s generally not the best choice.
Best: named state checking.
The best is to use a named state checking method. For example, iostreams have the fail member, so that you can write
while( !cin.fail() ) { ... }
For your own class it can look like this:
struct S
{
bool is_good() const { return ...; } // Whatever name.
};
So-so: explicit conversion to bool.
Next best is a explicit conversion operator. Having it explicit prevents if from being called inadvertently for passing one of your objects as a function argument. An explicit conversion operator is still used in a condition, so you can write e.g.
while( cin ) { ... }
which in C++11 invokes an
explicit operator bool () const { return !fail(); }
For your own class it can look like
struct S
{
explicit operator bool () const { return ...; }
};
Ungood: implicit conversion to "private" pointer type.
Third, if you're using a compiler that does not support explicit conversions, i.e. a C++03 compiler, and if for some inexplicable reason you do not want the named checking which is the best choice, then you can choose a result type that minimizes the chance of an inadvertent call.
In C++03 iostreams used an implicit conversion to void* (instead of to bool).
Some people advocate using the "safe bool idiom" where the result is a pointer to an, in C++03, type that's inaccessible to client code.
Absolutely worst: implicit conversion to bool.
The worst option of all is like
struct S
{
operator bool () { return ... }
};
With this
One cannot see from calling code what condition is being checked.
The operator can be inadvertently called for passing an S as function argument.
The conversion can not be called on a const object.
Adding a const only makes it slightly less bad.
It’s still very bad. :-)
It is operator bool() you need to overload to provide this behaviour. But please only do this if there is a sensible semantic meaning to the conversion, that is obvious and expected by all users of the class!
Your compiler will attempt to implicit cast the expression to bool, so you will need to add a typecast operator to your class, like this:
class SomeClass {
operator bool() {
return true; // a boolean expression should go here.
}
}
this will allow for your class to be casted to a boolean type and therefore let it be used in if, while etc...
It is however important to note that this allows implicit conversions from your type to bool and it is important to make sure that this makes sense.
Often it is more sensible to provide a method for the behavior, such as:
while (myObj.hasMoreElements())
or
if (someObj.isValid())
This makes it immediately clear what is being tested. However, if a conversion to bool makes sense, go for it.
You can overload any number of type conversion operators; the
traditional one was operator void*()() const, to return a null
pointer for false, and a non-null pointer (tradiionally this)
for true. In C++11, you can also overload explicit operator
bool() const, but this is not recommended if your compiler
doesn't yet allow explicit; the fact that bool is an
integral type, and that without the explicit, it will convert
to any other integral type, can lead to some surprising overload
resolutions .
If you do this, you should also overload operator!() const, so
that if ( ! myObj ) is well defined as well.
And finally, you should really reflect as to whether you want to
do this. The ostream classes get away with it because they're
part of the standard, and everyone sees, uses and knows them,
and the while ( someStream >> object ) idiom is ubiquitious.
But on the whole, it's misleading and an abuse of operator
overloading for any class which has more than two possible
states; an isValid or isReady or whatever function is more
appropriate.

Operator overloading and implicit conversion to bool in relation to safe bool idiom

I'm sure that some of my questions may have been asked before, so please let me know :).
First, an example:
#include <iostream>
struct A
{
typedef void (A::*funcptr)();
operator funcptr() {
std::cout << "funcptr" << std::endl;
}
};
int main()
{
A a;
if (a) {}
}
At if(a), operator funcptr() is called, but I'm not exactly sure what is happening here. I'm assuming the compiler looks for a conversion from an A to bool and finds operator functptr which is okay, but how does conversion work with pointers to member functions?
Also, if I changed operator funcptr() to operator int A::*() it would also work, but operator void A::* doesn't (I get cannot declare pointer to 'void' member), what is the rule I am missing there? (My questions are mostly related to trying to fully understand the safe bool idiom)
Also, if I declared operator bool() it would take precedence, so what are there rules for precedence?
To answer your second question, if you use
operator int A::*() { }
then you are creating a conversion operator which returns a pointer to an int member. Not a pointer to a member function. Since you can't have members of type void,
operator void A::*() { }
isn't valid.

Why is this operator called in C++?

I dont understand, why is the aaa operator called in the 2nd last line?
#include <iostream>
class MyClass
{
private:
typedef void (MyClass::*aaa)() const;
void ThisTypeDoesNotSupportComparisons() const {}
public:
operator aaa() const { return (true) ? &MyClass::ThisTypeDoesNotSupportComparisons : 0; }
};
int main()
{
MyClass a;
MyClass b;
if(a && b) {}
}
The compiler searches for the best match for (a && b).
Because the class doesn't have an operator that turns MyClass to a boolean, it searches for the best cast.
operator aaa() const is a cast to an aaa type pointer. Pointers can be evaluated in an if sentence.
Overloading typecasts
Conversion Functions (C++)
Your variables are used in an expression. The type itself does not have an operator&& defined for it, but it is convertible to a type (a pointer) that can be used in the expression. So the conversion operator is called.
It looks like a type cast operator. Oops, never mind, misread 'why is this operator called' for 'what is this operator called'
Ok, I tested your code and examined it some more. So operator aaa is a type cast to type aaa. Type aaa is a pointer to a member function of type void func(). ThisTypeDoesNotSupportComparisons is a function of type aaa. operator aaa gets called and returns the pointer to function.
I think it is called because the if allows to use pointers to functions as well. You can test if a pointer is NULL or not, and this is the closest the compiler can find, so if calls the operator aaa and tests if the pointer returned is zero.

Can I assign a object to a integer variable?

Let say I have a object. I'm assigning that to an integer.
MyClass obj1 = 100;//Not valid
Let's say, I have a parameterized constructor which accepts an integer.
MyClass(int Num)
{
// .. do whatever..
}
MyClass obj1 = 100;//Now, its valid
Likewise on any circumstance, does the vice-versa becomes valid?!.
eg) int Number = obj1;//Is it VALID or can be made valid by some tweeks
EDIT:
I found this to be possible using Conversion Functions.
Conversion functions are often called "cast operators" because they (along with constructors) are the functions called when a cast is used.
Conversion functions use the following syntax:
operator conversion-type-name ()
eg) Many have explained it neatly below
Yes, provided that the object is implicitly convertible to an int, either directly or through an intermediate object.
E.g. If your class have a conversion operator int it would work:
MyClass
{
public:
operator int() const { return 200; }
};
C++ constructors that have just one parameter automatically perform implicit type conversion. This is why conversion from int to MyClass works. To create conversion from MyClass to int you have to define operator int() inside MyClass.
Yes you can, using user defined conversions.
In your MyClass, define operator int()
So
class MyClass
{
int myVal;
public:
operator int() { return myVal;}
}
Yes, you need to add a conversion operator to MyClass
operator int();
MyClass is not an integer therefore you can't do int Number = obj1;
You should have a method or operator(stated by others) in MyClass that returns an int. (int number = obj1.GetNum();)