Is it possible to assign object to int? - c++

I have a CCounter class which holds and integer value protected by mutex. I've defined several operators like post/pre inc/dec returning an integer so I can do:
CCounter c(10);
int i = c++;
but what do I do with a simple assignment like i = c ? I tried to define friend operator= but it gives me
operator=(int&, const CCounter&)’ must be a nonstatic member function
error. Please, advise. Thanks.

You need to define a casting operator that casts from CCounter to int. Add this member to your class:
operator int() const {
return ...;
}

As you have found out, the assignment operator must be a member function of a class. As ints are not classes, you can't write operator=() for them. The alternative, as others have pointed out is to write a function that converts to an int. I would strongly suggest you write a named function like ToInt() to do this, rather than using a conversion operator, which can be the source of non-obvious bugs.

G'day,
Shouldn't you be defining an accessor function instead if you're just "getting" the current value of the counter?
Something like:
int GetCounter();
Anything else is sort of disguising the intention of what you're trying to do. IMHO Natch! (-:
HTH
cheers,

You need to define operator int() to allow the conversion of your class to an int. For example:
class CCounter
{
public:
CCounter(int val) : m_val(val)
{
}
operator int() const
{
return m_val;
}
private:
int m_val;
};
int main(int argc,char *argv[])
{
CCounter c(10);
int n = c;
std::cout<<n<<"\n";
return 0;
}

As said use the int() operator. Here a code snippet :
#include <iostream>
class CCounter
{
public:
CCounter(int i = 0) : _count(i) {}
operator int() { return _count; }
private:
int _count;
};
int main()
{
CCounter counter(4);
int c = counter;
std::cout << "Counter = " << c << std::endl;
return 0;
}

You said:
"I've defined several operators like post/pre inc/dec returning an integer".
Now that other answers provided you with a generic way to convert the object to an integer, I would recommend that you change these other operators so that they behave as typically expected.
For instance, pre increment typically returns a reference to the object itself, and post increment typically returns a temporary copy of the original object (prior to the incrementation).
CCounter& operator++() {
++m_val;
return *this;
}
CCounter operator++(int) {
CCounter tmp(*this);
++m_val;
return tmp;
}

Although you have been given a valid solution, I would also consider simply creating a normal function which returns int, such as int GetValue() const, to improve readability and ease of maintenance. Of course this is highly subjective.

#include<iostream>
using namespace std;
class CA {
public:
int a;
CA(int x):a(x)
{
}
operator int() const {
return a;
}
void operator ()() {
}
};
void main(){
CA obj = 100;
int k = obj;
obj();
}

Related

Why in below code return type is class type used for operator overloading?

I have been trying to understand operator overloading and did not get the use of return type as class type in the below program:
When I switch "overload" return type with "int" it works fine.
#include <iostream>
using namespace std;
class overload {
private:
int count;
public:
overload(int i)
: count(i)
{
}
overload operator++(int) //why return type is class type when i can use int
{
return (count++);
}
overload operator++() //why return type is class type when i can use int
{
count = count + 1;
return count;
}
void Display()
{
cout << "Count: " << count<<endl;
}
};
// Driver code
int main()
{
overload i(5);
overload post(5);
overload pre(5);
// this calls "function overload operator ++()" function
pre = ++i;
post = i++;
i.Display();
return 0;
}
The difference between the pre/post increment operators is that one works on the object directly (pre-increment: ++foo), and one needs to take a copy of the object and return that (post increment: foo++). A slightly more verbose way of writing this would be:
// return a new object that represents the old value
overload operator++(int)
{
overload oldValue(count); // take copy
count++; // increment this object
return oldValue;
}
// increment the count, and return a reference to this object
overload& operator++()
{
++count;
return *this;
}
Whilst you could return int (don't do that!), it will only lead to confusion. Effectively it would cause a few issues with code such as:
overload foo = ++someOtherFoo;
Which if you were to return int from ++, would effectively end up calling your constructor function (rather than copy constructor) to construct a new object. i.e.
overload foo = overload(++someOtherFoo);
That constructor might not be available, and so the code would fail.
If you want your object to automatically convert itself to an integer, then the correct way would be to overload the cast operator, e.g.
operator int () const
{
return count;
}
There are no restrictions on the return type of an overloaded operator. Here it can be int as well.
The code you show has the class type as return type to facilitate the other statements in the code as below if ever the constructor of the overload class is marked explicit;
For example with:
explicit overload(int i)
: count(i)
{
}
and
int operator++(int) //return type is int
{
return (count++);
}
int operator++() //return type is int
{
count = count + 1;
return count;
}
The following will fail to compile:
pre = ++i; //will not work
post = i++; //will not work
This is because the implicit copy assignment operator will no longer be viable for conversion from int to const overload.
See Demo
Note that the Canonical implementations of the prefix and postfix increment/decrement operators return overload& and overload respectively.
Although canonical form of pre-increment/pre-decrement returns a reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value

Use class with operator []

i am trying to implement a "Integer" class with expect that it will work like a build-in type int. But i am having a problem: i can't use this class in operator [] like int See my code below:
#include <iostream>
using namespace std;
class Integer
{
private:
int Value;
public:
Integer(int x = 0)
{
Value = x;
}
void SetValue(int x)
{
Value = x;
}
int GetValue()
{
return Value;
}
Integer& operator [] (Integer X);
};
Integer& Integer::operator [] (Integer X)
{
// Code
}
int main()
{
Integer X[10];
Integer I(5);
int i = 5;
for(int i=0; i<10; ++i)
X[i].SetValue(i+1);
cout << X[i].GetValue() << endl; // It still work
cout << X[I].GetValue() << endl; // Doesn't work
return 0;
}
What is a way (exclude cast operator) to make operator [] understand my Integer type like it does with int?
You are thinking about this the wrong way around. You don't need to overload the [] operator on your own class, you actually need your class to be convertable to int, which can be done by overloading the cast operator.
class Integer
{
public:
operator int () const { return Value; }
};
There's a bit of confusion here. The declaration of an array of type T takes the form
T t[n];
where n is a compile time evaluable constant expression for the array size.
This does not invoke any [] operator defined within T, and neither does a subsequent access of an element via the expression t[i] for an integral type i.
If, in your case, you want X[I] to be compilable then you need to provide an operator that allows I to be treated as an array index (more formally the language requires a primitive integral type). A cast operator to int is the obvious choice, with
operator int() const
{
return Value;
}
being the implementation.
You'll need to add a type cast operator to your class. This allows your class to be converted to a compatible type. See here for more information: http://www.cplusplus.com/doc/tutorial/typecasting/
This function should do the trick for your class.
operator int() const { return GetValue(); }
Actually, you don't need to overload the [] operator.
You just need to make sure that you can convert your Integer into an int with int int operator.
Something like this would work better.
operator int() const
{ return GetValue(); }
Then you should also be carefull with your prints.
X[i].GetValue() is wrong since i = 10 in your exemple. This will result in an execution error.
X[I].GetValue() is wrong in your exemple because de conversion between your class and an int is not possible without I.getValue(). I am surprise this doesn't result in a compilation error but overloading the int operator will result this issue tho.

Default return of class instance without member function

Is it possible to make a class return a particular member variable by default when the object is used somewhere(without using a getter member function)?
If I have this class:
class A{
public:
A(int nr) : number(nr){};
~A();
int getNr(){ return this->number };
int number;
};
To set and get its number later in the program, I can do this:
int main(){
A thing(23);
std::cout<<"Your number is: "<<thing.getNr();
return 0;
}
But what I would like to do is this:
std::cout<<"Your number is: "<<thing;
And get the exact same result, make it return the member variable "number" by default. Can this be done/set somehow?
I know somebody might be thinking "Why not just use integers as they are for that?" - I'm making a class which should be able to "turn into" any type and then act like the assigned type, it would be nice if I could make it act like ints, doubles, strings in that regard too later.
Your specific example invokes the << stream insertion operator on an A. This operator can be overloaded to do what you want:
#include <iostream>
class A{
public:
A(int nr) : number(nr) { }
~A() { }
int getNr() const { return this->number; }
int number;
};
std::ostream& operator<<(std::ostream& os, const A& a) {
os << a.getNr();
return os;
}
int main(int, char *[]) {
A a(42);
std::cout << a << std::endl; // prints 42
}
Note here I have made some other minor fixes to your code (fixed a missing ; and removed some unnecessary ones; added const to getNr()).
For other situations, such as passing arguments of type A to functions that accept parameters of a different type, you can define user-defined conversion operators that are called by the compiler to convert an A to a different type. For example:
void doSomething(int x) {
// ...
}
class A{
public:
A(int nr) : number(nr){}
~A(){}
int getNr(){ return this->number; }
int number;
operator int() { return getNr(); }
};
int main(int, char *[]) {
A a(42);
doSomething(a); // calls operator int() above
return 0;
}
Be careful with user-defined conversion operators. In particular, it's often best to mark them explicit and use static_cast<T>() to trigger the conversion. Implicit conversions can quickly get you into trouble with overload resolution.

How do I create a class that can initialize C++ data types?

The title basically says it all. I mainly want to do this so that I can create an object (say, a custom string object) that can initialize the parameters of other functions in other APIs. Here's an example of me trying to get a custom integer class to work:
#include <iostream>
using namespace std;
class test
{
public:
int member;
test(int i) : member(i) {}
friend int &operator=(int &i, test t);
};
int &operator=(int &i, test t)
{
return (i = t.member);
}
int main()
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
Unfortunately I receive an error saying that operator= needs to be a member function. I understand the C++ standard's goal in preventing static and non-member overloads for the assignment operator from being implemented, but is there any other way to do this? Thanks for any help/suggestions!
This is not done with an assignment operator but with an overloaded typecast. This would make your main function work like expected:
#include <iostream>
using namespace std;
class test
{
public:
int member;
test(int i) : member(i) {}
operator int() const {return member;}
};
int main()
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
What you are trying to do needs an conversion operator
operator int()
{
return this->member;
}
For the class you are trying to write(containing only integer members), You do not need to overload the = operator.
= operator is one of the member functions that is generated by the compiler by default for every class. Caveat is, it does a simple bit by bit copy(shallow copy) of class members, since you have only integers it should be good enough for you.
You would need to overload the = operator if you had dynamically allocated pointers as member functions, because in that case a shallow copy of those pointers would result in all the objects containing a member pointer pointing to the same dynamic memory location & if one of the object finishes it lifetime, other objects are left with a dangling pointer.
As #Tony, aptly points in out comments Shallow copy is usually bad but not always. See his comments for a scenario.
If at all you want to overload the assignment operator check out the Copy and Swap Idiom to do it right way.
You should also check out the Rule of Three.
Try this:
class test
{
public:
int member;
test(int i) : member(i) {}
operator int() {return this->member;}
};
int main(void)
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
The assignment operator cannot be a friend function. The assignment operator can only be declared as a non-static member function. This is to ensure that it receives the L-value as its first operand. The same is true for the [], (), and -> operators. In your case, since int is an build-in type, you cannot use member function. You can implement operator int() to cast your user-defined type to int.

C++: Overloading operator=

Okay so I have a class that has 'weak typing' I.E. it can store many different types defined as:
#include <string>
class myObject{
public:
bool isString;
std::string strVal;
bool isNumber;
double numVal;
bool isBoolean;
bool boolVal;
double operator= (const myObject &);
};
I would like to overload the assignment operator like this:
double myObject::operator= (const myObject &right){
if(right.isNumber){
return right.numVal;
}else{
// Arbitrary Throw.
throw 5;
}
}
So that I can do this:
int main(){
myObject obj;
obj.isNumber = true;
obj.numVal = 17.5;
//This is what I would like to do
double number = obj;
}
But when I do that, I get:
error: cannot convert ‘myObject’ to ‘double’ in initialization
At the assignment.
I have also tried:
int main(){
myObject obj;
obj.isNumber = true;
obj.numVal = 17.5;
//This is what I would like to do
double number;
number = obj;
}
To which I get:
error: cannot convert ‘myObject’ to ‘double’ in assignment
Is there something I am missing? or is it simply not possible to do a conversion like that by overloading operator=.
Overloading operator= changes the behaviour when assigning to objects of your class type.
If you want to provide implicit conversion to other types you need to supply a conversion operator, e.g.
operator double() const
{
if (!isNumber)
throw something();
return numVal;
}
What you really want are conversion operators.
operator double() const { return numVal; }
operator int() const { ...
That said, you'd probably like boost::variant.
for that to work, you need to implement a conversion operator from your object to something that can be converted into a double
The return value of operator=() cannot be used as you have tried to demonstrate. If you think of the overloaded operator as a function in it's own right, it may make more sense.
For example:
int main() {
myObject obj, obj2;
obj.isNumber = true;
obj.numVal = 17.5;
obj2.operator=(obj); // equivalent to obj2 = obj
}
The reason number = obj; doesn't work is because you've defined myObject::operator=(), whereas number would be using double::operator=() (okay, technically there is no double::operator=() since it's a fundamental type and not a class...just work with me here).
An interesting note is that this function behaves like any other function in that the return value (return right.numval;) is ignored when it's not used. However, the return value can be assigned or used like the return value of any other function, so if you really wanted you could do something like this:
int main() {
myObject obj, obj2;
obj.isNumber = true;
obj.numVal = 17.5;
double number;
// number = obj; still won't work.
number = obj2 = obj; // equivalent to number = obj2.operator=(obj)
}
This is only so useful. As others have mentioned, you really want to look into conversion operators when trying to assign myObject objects to fundamental types.
To make a class assignable to a double, operator= must be defined differently.
double operator=(myclass&) is wrong.
What would work, is a friend operator= outside your class, which accepts double and myclass&.