define both operator void* and operator bool - c++

I tried creating a class with one operator bool and one operator void*, but the compiler says they are ambigous. Is there some way I can explain to the compiler what operator to use or can I not have them both?
class A {
public:
operator void*(){
cout << "operator void* is called" << endl;
return 0;
}
operator bool(){
cout << "operator bool is called" << endl;
return true;
}
};
int main()
{
A a1, a2;
if (a1 == a2){
cout << "hello";
}
}

The problem here is that you're defining operator bool but from the sounds of it what you want is operator ==. Alternatively, you can explicitly cast to void * like this:
if ((void *)a1 == (void *)a2) {
// ...
}
... but that's really bizarre. Don't do that. Instead, define your operator == like this inside class A:
bool operator==(const A& other) const {
return /* whatever */;
}

You could call the operator directly.
int main()
{
A a1, a2;
if (static_cast<bool>(a1) == static_cast<bool>(a2)){
cout << "hello";
}
}
In this case, though, it looks like you should define operator==() and not depend on conversions.

Related

C++ type conversion operator

I am studying operator overloading, there are some parts that are difficult to understand.
See this example code.
class A {
private:
char a;
int b;
double c;
public:
A(char _a = 'a', int _b = 99, double _c = 1.618) :a(_a), b(_b), c(_c){
}
public:
operator char() const {
cout << "operator char() called" << endl;
return this->a;
}
operator int() const {
cout << "operator int() called" << endl;
return this->b;
}
operator double() {
cout << "operator double() called" << endl;
return this->c;
}
};
int main(void) {
A a;
char b = a;
int c = a;
double d = a;
printf("%c\n", b);
printf("%d\n", c);
printf("%f\n", d);
return 0;
}
I made this code to test for type conversion operator and expected that the appropriate function would be called for each type of data.
But the result is..
operator double() called
operator double() called
operator double() called
<-- strange character is gone on board!
1
1.618000
I can not understand why the results are not as follows.
operator char() called
operator int() called
operator double() called
a
99
1.618
Why is double operator called when converting to char and int?
Have a good day! :)
You forgot the const on the double conversion operator:
operator double() const { // <---------------------------
cout << "operator double() called" << endl;
return this->c;
}
};
As in your example a is not const, the double conversion is the best match. If you fix that you get the expected output.
Live example
...some opinion based PS:
I didnt find what the core guidelines say about conversion operators, but if I had to make up a guideline for conversion operators it would be: Avoid them. If you use them, make them explicit. The surprising effects of implicit conversion outweigh the benefits by far.
Just as an example, consider std::bitset. Instead of offering conversion operators it has to_string, to_ulong and to_ullong. It is better to have your code explicit. A a; double d = a; is a little bit mysterious. I would have to look at the class definition to get an idea of what is really going on. On the other hand A a; double d = a.as_double(); can do the exact same thing, but is way more expressive.
Yea so the problem is, that you made all operators const except for the double operator. I am still a bit surprised because this const just means that the operator call does not modify the class members. Still it seems that only the double operator is called for all 3. I would all 3 op's make const and then it will work properly.
If someone has an explanation why this happens, I would also like to know.
Cheers.
operator char() const { // here is const
cout << "operator char() called" << endl;
return this->a;
}
operator int() const { // here is const
cout << "operator int() called" << endl;
return this->b;
}
operator double() { // here is no const
cout << "operator double() called" << endl;
return this->c;
}

Compare two objects in vector iteration C++

How to implement the comparison function in this case?
void remove(const Object1 &object1) {
for(auto &object2 : objectVector) {
if(object1 == object2) {
/*....... */
}
}
}
You are asking 2 questions:
How can objects be made comparable:
By implementing operator== for the class. Be sure you override operator != then too.
As a member function:
bool Object1::operator ==(const Object1 &b) const
{
// return true if *this equals b;
}
Or as a free function:
bool operator ==(const Object1 &a, const Object1 &b)
How can objects with a given value be removed from a vector:
The easiest way is to use std::remove:
objectVector.erase(std::remove(objectVector.begin(), objectVector.end(), object1), objectVector.end());
You can remove objects also while iterating through the vector, but you have to keep in mind that the vector iterator is invalidated then. You may not further iterate on the vector then.
An object of your class can contain different types and number of members so let's say that you have a class A:
class A{
int x,
float y;
char* z;
};
And you have two instances:
A a1;
A a2;
To compare:
if(a1 == a2) // compile-time error
;// DoSomeThing
Above you get the error because the compiler doesn't know which fields will be compared against each other. The solution is to overload the equals operator "==" to work on objects of your class.
class Student{
public:
Student(std::string, int age);
std::string getName()const;
int getAge()const;
bool operator == (const Student&);
private:
std::string name;
int age;
};
Student::Student(std::string str, int x) :
name(str), age(x){
}
bool Student::operator == (const Student& rhs){
return age == rhs.age;
}
std::string Student::getName()const{
return name;
}
int Student::getAge()const{
return age;
}
int main(){
Student a("Alpha", 77);
Student b("Beta", 49);
if(a == b)
std::cout << a.getName() << " is the same age as " <<
b.getName() << std::endl;
cout << endl << endl;
return 0;
}
Now the compiler knows how to compare objects of your class and know what the equals operator compares on your ojects members.
if object is a class you can override the operator == in the class as a friend function, or you can implement your own function bool isEqual(Object1 o1, Object1 o2) { if(something) return true; return false; }

Segmentation fault in conversion operator (reference to member)

Why is this causing segmentation fault?
#include <iostream>
struct A
{
std::string str;
A(std::string const& pstr) : str(pstr)
{}
operator std::string const&() const { return str; }
};
bool operator==(A const& a, A const& b)
{ return std::string(a) == b; }
int main()
{
A a1("hola"), a2("adios");
std::cout << (a1 == a2) << std::endl;
return 0;
}
After all, the member str is still alive when doing the conversion.
http://coliru.stacked-crooked.com/a/e7453471bc1af93e
You have an recursive call to your operator==. Your constructor of A defines an implicit cast of string to A. To not allow that, add explicit to the constructor, but then you are missing a operator== for string and A;
Just edited your code and it worked for me:
return std::string(a) == std::string(b);

Getting garbage value while doing chaining of assignment of class objects, using assignment operator overloading which returns class object by value

In assignment operator overloading, If I return the object by reference like below
One& operator=( const One& obj).
Then program works fine.
But if when I return by value, like below
One operator=( const One& obj)
Then o1 gets garbage value. Can anybody explain why return by value does not work in assignment operator overloading?
class One
{
public:
One(int a1, int b1) {
a = a1; b = b1;
}
int a;
int b;
One operator=( const One& obj) {
cout<<"\nOperator= is called\n"; a = obj.a; b = obj.b;
}
};
int main()
{
One o1(5,5);
One o2(10,10);
One o3(15,15);
cout << "\no1.a=" << o1.a << ", o1.b=" << o1.b << endl;
o1 = o2 = o3;
cout << "\no1.a=" <<o1.a << ", o1.b=" << o1.b << endl;
cout << "\no2.a=" <<o2.a << ", o2.b=" << o2.b << endl;
cout << "\no3.a=" <<o3.a << ", o3.b=" << o3.b << endl;
return 0;
}
Output:
o1.a=-13360, o1.b=0
o2.a=15, o2.b=15
o3.a=15, o3.b=15
Why o1 object showing garbage value in case of return by value in assignment operator. It works fine when return by reference. why?
o1 = o2 = o3; is evaluated as o1 = (o2 = o3);
That requires o2 = o3 to return something, and o1 is set to that value. But your overload currently doesn't. (Formally it means that the behaviour of your code is undefined). If you rewrite to
One& operator=(const One& obj)
{
std::cout << "\nOperator= is called\n";
a = obj.a;
b = obj.b;
return *this; // i.e. return a reference to self.
}
then all will be well. That said, the cool cats will use
One& operator=(One obj/*pass by value to exploit compiler optimisations*/)
{
std::cout << "\nOperator= is called\n";
std::swap(*this, obj);
return *this;
}
Reference: What is the copy-and-swap idiom?
The code of the = operator should be this:
One & operator=(const One& obj)
{
cout << "\nOperator= is called\n";
a = obj.a;
b = obj.b;
return *this;
}
One operator=( const One& obj)
{ cout<<"\nOperator= is called\n"; a = obj.a; b = obj.b; }
You do not have any return expression in your function definition, resulting in undefined behavior. That's why the operator does not work as it should.
In case you are using the gcc compiler, I would suggest you enable the -Wall option, which would have produced a warning, indicating the failure. In case you are using sth different there's probably an equivalent option available.
You may also want to take a look at the Copy-and-Swap Idiom which provides an advanced insight in the creation of a properly working copy-assignment operator.

C++ operator overloading affect in-class operator functions

What if i overload the != operator and use class!= inside one of other operator overloaders, does it accept it as non-overloaded or overloaded? I am trying to create a noob_ptr (a kind of custom-pointer wraper i am thinking of)
class noob_ptr
{
private: //does this change the behaviour? public? protected?
bool operator!=(noob_ptr x)
{
...
}
bool operator,(noob_ptr y)
{
...
if(y!=z)...
...
}
...
}
Does below example cancel usage of overloaded-operator in my class?
class noob_ptr
{
protected: //or public
bool operator,(noob_ptr y) //yes, z is also a noob_ptr
{
...
if(y!=z)...
...
}
...
private:
bool operator!=(noob_ptr x)
{
...
}
}
If type of z is also a noob_ptr, then the answer is YES, it will call the overloaded operator != for your class.
Also, I'd suggest you this comparison method signature:
bool operator != (const noob_ptr& x) const;
so it can be used for constant pointers and also avoid object copying while calling the overloaded operator.
UPD: If you declare operator != as private, then it'll be available in all member functions of noob_ptr class, friend classes and functions of noob_ptr class, and for all other usages will result in a compilation error with a message like: "operator != is inaccessible due to its protection level"
If the operands you supply are ones for which the language's built-in != will work, then that's what gets used. If they're of user-defined types, then it'll search for a user-defined operator!= that's defined for those types (or some types that support implicit conversion from those types).
C++ will always use the "best match" which is the closest in qualifiers, access specifiers such as private, scope, namespace, etc.
So, if there is a global namespace operator!= and a class one (that lacks the left-hand-side argument which is assumed to be the class& or const class& if the method is const -- which it should be), then inside the class (namespace) you will get the one inside the class.
If there is only one between the global namespace and the class, you will obviously get that one.
The following code demonstrates between global and class scope. You can extend this by adding const qualifiers, etc.
#include <iostream>
using namespace std;
// Forward declaration to use without the class definition
class X;
bool operator!=( int lhs, const X& rhs) {
cout << "bool operator!=( int lhs, const X& rhs)" << endl;
return false;
}
bool operator!=(const X& lhs, const X& rhs) {
cout << "bool operator!=(const X& lhs, const X& rhs)" << endl;
return false;
}
bool operator!=(const X& lhs, int rhs) {
cout << "bool operator!=(const X& lhs, int rhs)" << endl;
return false;
}
// Note: Can't do: bool operator!=(int lhs, int rhs) -- already defined
class X {
private:
int x;
public:
X(int value) : x(value) { }
bool operator !=(const X& rhs) {
cout << "bool X::operator !=(const X& rhs)" << endl;
return true;
}
bool operator !=(int rhs) {
cout << "bool X::operator !=(int rhs)" << endl;
return true;
}
void f() {
X compare(1);
cout << "X::f()" << endl;
cout << (5 != 3) << endl; // Uses built-in
cout << (*this != 3) << endl; // Uses member function
cout << (*this != 1) << endl; // Uses member function
cout << (1 != *this) << endl; // There can be no member function, uses global namespace
cout << (*this != compare) << endl;
}
};
void f(const X& arg) {
cout << "f()" << endl;
X compare(1);
cout << (5 != 3) << endl; // Uses built in
cout << (arg != 3) << endl; // Uses global namespace
cout << (arg != 1) << endl; // Uses global namespace
cout << (1 != arg) << endl; // Uses global namespace
cout << (arg != compare) << endl; // Uses global namespace
}
int main(int argc, char **argv) {
X x(1);
x.f();
f(x);
return 0;
}