I have a class named mc_int which is actually a int, with some special abilities. It has set operator int():
mc_int::operator int() {
return value; //int mc_int::value - the real int value of the class
}
But when I try to cout<< the class, I must always cast the class to int (cout<<(int)mc_int_instance, because I get the error:
More than one operator "<<" matches these operands.
As well, this may be caused by the fact, that the class also has << operator defined. What to do here?
If you're using C++11, you can make use of the explicit keyword to make it so you have to explicitly convert to int. More information here:
explicit mc_int::operator int()
Now when you use it should use the << operator method you defined and it should no longer be ambiguous to the compiler. If you do want to use the int, just cast to it like you did or with static_cast<int>(the_object).
Related
If the following class, Foo, is defined. It is said it overloads the unary ampersand (&) operator:
class Foo {
public:
Foo* operator&() { return nullptr; }
};
I think in this case, (reglardless of the fact that you can get the address of such an object by means of std::addressof() and other idiomatic tricks) there is no way to access/choose the original unary ampersand operator that returns the address of the object called on, am I wrong?
By overloading however, I understand that there is a set of functions of which one will be selected at compile-time based on some criteria. But this thinking doesn't seem to match the scenario above.
Why is it then called overloading and not something else like redefining or replacing?
Consider the following code:
int x;
Foo y;
&x; // built-in functionality
&y; // y.operator&();
We have two variables of different types. We apply the same & operator to both of them. For x it uses the built-in address-of operator whereas for y it calls your user-defined function.
That's exactly what you're describing as overloading: There are multiple functions (well, one of them is the built-in functionality, not really a "function") and they're selected based on the type of the operand.
You can't redefine a function or operator in C++, you can add only new use to it, defining new set of arguments. That's why it called overloading instead of redefining.
When you overload operator as a member of class you
1) defined it with first argument supposed to be an instance of that class
2) gave it access to all members of that class.
There are still definitions of operator& with different arguments and you have a non-zero chance to create situation where use of operator would be ambigous.
I want to overload the operator = and I have the following operator-function
int IntegerClass::operator=(IntegerClass integer) {
return integer.number;
}
This should be correct?
In another class I want to assign the objects private member (int) to another int i.e.
int x = integerClass;
but when I compile I get the following error
error: cannot convert 'std::IntegerClass' to 'int' in initialization
What is wrong with my implementation of operator-overloading and how should the function look like?
Your operator overloads assignment of one IntegerClass to another, but you're trying to assign (actually it's initialization) to a built in int. You need to define an implicit conversion operator.
The code should be something like this (sorry I don't remember the exact syntax)
IntegerClass::operator int() {
return number;
}
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 am trying to write bool-conversion operator for std::bitset
I tried:
template<size_t size>
operator bool(std::bitset<size> & b)
{
return b.any();
}
but I got
error C2801: 'mynamespace::operator bool' must be a non-static member
from my visual-studio.
But when I look up C2801 explanation it says nothing about conversion operators (only about =, ->, [],())
So, is it possible to somehow write "Conversion std::bitset to bool operator?"
(I can not call b.any() in my if-statements, because the same code must run when std::bitset is replaced with unsigned or something
typedef std::bitset<x> Bitset;
//typedef unsigned Bitset;
so the ideal syntax will be like:
Bitset b = whatewer;
if(b)
doStuff();
)
If this overloading is not possible, what is the recommended workaround?
so far I use it like:
if(b == Bitset(0))
doStuff();
but I dont like it.
Thank you
As the error message says, the conversion operator must be a non-static member of a class. That is true.
I can not call b.any() in my if-statements, because the same code must run when std::bitset is replaced with unsigned or something.
If that is your problem, then you can use function overload, and call it passing the argument which will return a boolean value:
template<typename T>
bool to_bool(T const & b)
{
return b; //implicit conversion (if allowed) for all other types
}
template<size_t N>
bool to_bool(std::bitset<N> const & b)
{
return b.any();
}
then use it as:
if (to_bool(whatever))
{
}
It will call the correct overload. If the type of whatever is std::bitset<N> then the second overloaded function will be called, or else the first one will be called.
§12.3.2/1: "A member function of a class X with a name of the form [...] specifies a conversion from X to the type specified..." (C++11 uses the same section number and nearly the same wording, adding only that the function takes no parameters).
The other possible way to define a conversion is a constructor (§12.3.1), which is obviously a class member as well.
In short, yes, conversions must always be defined as member functions.
One way to do what you want would be to write a wrapper around std::bitset that provides the conversion you care about:
template <int size>
class mybitest {
std::bitset<size> bits;
public:
operator bool() { return bits.any(); }
}
But if you decide to do that, you'll need to write forwarding functions for essentially all the pieces of bitset you're using (ctors, assignment, etc.)
The standard is a bit unclear on this (12.3.2):
A member function of a class X having no parameters with a name of the form [...] specifies a conversion from X to the type specified by the conversion-type-id. Such functions are called conversion functions. No return type can be specified. If a conversion function is a member function, the type of the conversion function (8.3.5) is “function taking no parameter returning conversion-type-id”.
The first sentence seems to imply that only member functions can be conversion functions, but I'm not sure what the purpose of the conditional "if a conversion function is a member function" is.
I'd take the first sentence as binding and conclude that a conversion function must be a member function.
in case this helps somebody, you can actually provide a not operator instead
template<size_t size>
operator !(std::bitset<size> & b)
{
return !b.any();
}
and use it like so using the !! idiom:
if (!!whatever)
{
}
still not ideal, but a bit closer I think.
C++ does not allow polymorphism for methods based on their return type. However, when overloading an implicit conversion member function this seems possible.
Does anyone know why? I thought operators are handled like methods internally.
Edit: Here's an example:
struct func {
operator string() { return "1";}
operator int() { return 2; }
};
int main( ) {
int x = func(); // calls int version
string y = func(); // calls string version
double d = func(); // calls int version
cout << func() << endl; // calls int version
}
Conversion operators are not really considered different overloads and they are not called based on their return type. The compiler will only use them when it has to (when the type is incompatible and should be converted) or when explicitly asked to use one of them with a cast operator.
Semantically, what your code is doing is to declare several different type conversion operators and not overloads of a single operator.
That's not return type. That's type conversion.
Consider: func() creates an object of type func. There is no ambiguity as to what method (constructor) will be invoked.
The only question which remains is if it is possible to cast it to the desired types. You provided the compiler with appropriate conversion, so it is happy.
There isn't really a technical reason to prevent overloading of functions on the result types. This is done in some languages like Ada for instance, but in the context of C++ which has also implicit conversions (and two kind of them), the utility is reduced, and the interactions of both features would quickly leads to ambiguities.
Note that you can use the fact that implicit conversions are user definable to simulate overloading on result type:
class CallFProxy;
CallFProxy f(int);
class CallFProxy {
int myParameter;
CallFProxy(int i) : myParameter(i) {}
public:
operator double() { std::cout << "Calling f(int)->double\n"; return myParameter; }
operator string() { std::cout << "Calling f(int)->string\n"; return "dummy"; }
};
Overload resolution chooses between multiple candidate functions. In this process, the return type of candidates is indeed not considered. However, in the case of conversion operators the "return type" is critically important in determining whether that operator is a candidate at all.