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; }
Related
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.
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.
Here is my code example:
class X
{
public:
void f() {}
};
class Y : public X
{
public:
X& operator->() { return *this; }
void f() {}
};
int main()
{
Y t;
t.operator->().f(); // OK
t->f(); // error C2819: type 'X' does not have an overloaded member 'operator ->'
// error C2232: '->Y::f' : left operand has 'class' type, use '.'
}
Why the compiler is trying to "move the responsibility" for operator-> from Y to X? When I implement X::op-> then I cannot return X there - compile error says "infinite recursion" while returning some Z from X::op-> again says that Z doesn't have operator->, thus going higher and higher in hierarchy.
Can anyone explain this interesting behavior? :)
The problem is that operator -> is supposed to return a pointer, not a reference. The idea is that operator -> should return a pointer to the real object that should have the pointer applied to it. For example, for a class with an overloaded operator ->, the code
myClass->myValue;
translates into
(myClass.operator-> ())->myValue;
The problem with your code is that operator -> returns a reference, so writing
myClass.operator->().f();
is perfectly legal because you're explicitly invoking the operator, but writing
myClass->f();
is illegal, because the compiler is trying to expand it to
myClass.operator->()->f();
and the return type of operator-> isn't a pointer.
To fix this, change your code so that you return a pointer in operator ->. If you want to overload an operator to return a reference, overload operator *; pointer dereferences should indeed produce references.
Because that's how overloaded -> works in C++.
When you use overloaded ->, expression a->b is translated into a.operator->()->b. This means that your overloaded operator -> must return something that will itself support another application of operator ->. For this reason a single invocation of overloaded -> might turn into a long chain of invocations of overloaded ->s until it eventually reaches an application of built-in ->, which ends the chain.
In your case you need to return X* from your overloaded ->, not X&.
The syntax is wrong, should be:
T->T2
T2* T::operator ->();
Look at wikipedia's article: Operators in C and C++
If you want to overload, you must use the right syntax for the overloaded operator
You probably want:
class Y : public X
{
public:
X* operator->() { return this; }
void f() {}
};
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
Can somebody tell me what precisely
operator std::string()
stands for?
It is a conversion operator that allows the object to be explicitly or implicitly casted to std::string. When such a cast occurs, the operator is invoked and the result of the cast is the result of the invocation.
As an example of an implicit cast, suppose you had a function that accepted type std::string or const std::string&, but not the given object type. Passing your object to that function would result in the conversion operator being invoked, with the result passed to the function instead of your type.
It is a cast operator. Any class that defines this type can be used anywhere a std::string is required. For instance,
class Foo {
public:
operator std::string() const { return "I am a foo!"; }
};
...
Foo foo;
std::cout << foo; // Will print "I am a foo!".
Cast operators are almost always a bad idea, since there is invariably a better way to achieve the same result. In the above case, you are better off defining operator<<(std::ostream&, const Foo&).