I run into a strange c++ operator.
http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f0097af7530fe57a100b00d
class Number {
..
operator unsigned short () const;
};
I called this operator as:
a Number(..);
unsigned short b = a.operator unsigned short();
this works, but I can't understand how it works.
first, this operator don't have a return value.
seconds, a.operator unsigned short() is really strange to me. What is a better way to call this?
if I call :
unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?
The function is a user defined conversion operator. More details can be found at http://en.cppreference.com/w/cpp/language/cast_operator.
You said,
this operator don't have a return value. seconds,
The return values of the user define conversion operators is the explicit type. In your case, the return type is unsigned short.
You asked:
What is a better way to call this?
You could do an explicit cast to invoke the function.
Number n;
unsigned short s = (unsigned short)v;
It is also called when an conversion is required by the compiler.
void foo(unsigned short s) {}
Number n;
foo(n); // Number::operator unsigned short() is called to cast
// n to an unsigned short.
You asked:
if I call : unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?
Yes. The user defined operator function gets called.
Here's the relevant sections from the C++ Draft Standard (N3337):
12.3.2 Conversion functions
1 A member function of a class X having no parameters with a name of the form
...
[ Example:
struct X {
operator int();
};
void f(X a) {
int i = int(a);
i = (int)a;
i = a;
}
In all three cases the value assigned will be converted by X::operator int(). — end example ]
This is the conversion operator. A conversion function typically has the general form
operator type() const;
where type represents a type. It means objects of type Number can be converted to short int.
The conversion operator have no explicitly stated return type and no parameters, because the return type is exactly the type in the signature.
It's a conversion function, called to convert your type into a specific other type under various conditions, and it's covered in ISO C++11 12.3.2 Conversion functions.
In your case, it's called when the Number instance needs to be converted into an unsigned short.
By providing conversion operators, you can take full control over what happens during the conversion process, including such evil as the following:
#include <iostream>
struct X {
int val;
X(int v) { val = v; };
operator int() { return val + 1; }; // pure evil
friend std::ostream& operator<< (std::ostream&, X&);
};
std::ostream& operator<< (std::ostream &out, X &x) {
out << x.val;
return out;
}
int main (void) {
X xyzzy (42);;
std::cout << xyzzy << '\n';
std::cout << (int)xyzzy << '\n';
return 0;
}
which will output the value when you use the instance directly, but output something totally different when you cast it.
Now granted, that's rather evil and not a really good use case but you can use this for things such as rounding floats rather than truncating them, when converting to an integer:
#include <iostream>
struct X {
double val;
X(double v) { val = v; };
operator int() { return (int)(val + 0.5); };
friend std::ostream& operator<< (std::ostream&, X&);
};
std::ostream& operator<< (std::ostream &out, X &x) {
out << x.val;
return out;
}
#define E 2.718281828456
int main (void) {
X xyzzy (E);
double plugh = E;
std::cout << plugh << " -> " << (int)plugh << '\n';
std::cout << xyzzy << " -> " << (int)xyzzy << '\n';
return 0;
}
The output of that code is:
2.71828 -> 2
2.71828 -> 3
As a supplement for the first answer, when you use keyword explicit, note the difference, using explicit would force the programmer to assert his intention to convert using a cast:
class Number {
private:
int num;
public:
explicit Number(int number) : num(number) {} // constructor
explicit operator unsigned short () const { // conversion operator
return num;
}
};
int main() {
Number classTypeNumber(10);
// unsigned short convertToUshortNumber = classTypeNumber; // error
// implicit conversion is not allowed.
// now you should explicit convert the instance first.
// typedef unsigned short int __u_short in types.h file.
unsigned short convertToUshortNumber = static_cast<__u_short>(classTypeNumber);
cout << convertToUshortNumber;
}
Related
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.
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.
'int' and 'double' conversion functions is 'explicit' and in this code why have I permit for use this conversion instead of error message?
If I delete all my conversion overload functions code occur 'conversion error'
class Person
{
public:
Person(string s = "", int age = 0) :Name(s), Age(age) {}
operator string() const { return Name; }
explicit operator int() const{ return 10; } // ! Explicit
explicit operator double()const { return 20; } //! Explicit
operator bool()const { if (Name != "") return true; return false; } // using this
};
int main(){
Person a;
int z = a;
std::cout << z << std::endl; // Why print "1"? Why uses bool conversion?
}
I this it is answer:
Because 'a' can not be convert to int or double it occur error, but because it has bool conversion function, which can convert to int and int to double, code use this function.
int z = a;
Looks innocuous, right?
Well, the above line calls the implicit bool-conversion-operator, because that's the only way you left it to get from Person to int, and that only needs one user-defined conversion (the maximum allowed).
This is the reason for the safe-bool-idiom before C++11, and the major reason for the general advice to mark conversion operators and single-argument ctors explicit unless they are not transformative nor lossy.
If you want to see it for yourself, fix your code and trace invocation of your operator bool.
I know that there is no legal overload based on return type in C++; i.e.
you cannot do something like:
int operator ++ getOwner();
char operator ++ getOwner();
However, I stumbled upon the following:
https://stackoverflow.com/a/9569120/1376317
class Proxy
{
My const* myOwner;
public:
Proxy( My const* owner ) : myOwner( owner ) {}
operator int() const
{
return myOwner->getInt();
}
operator char() const
{
return myOwner->getChar();
}
};
My question is how does operator overload work in this configuration. How do you call this in your main.cpp to get this kind of overloading. How does the compiler deduce , how to call the right overload?
My question is how does operator overload work in this configuration.
These operators provide implicit conversions. That means that this class can be used in many contexts where an int or char is expected, and will use these operators to provide the expected value.
How do you call this in your main.cpp to get this kind of overloading.
Here are a few examples of implicit conversions:
Proxy p = whatever();
int i = p; // convert to int
char c = p; // convert to char
long l = p; // ERROR: ambiguous
void f(int);
f(p); // convert to int
void g(int);
void g(char);
g(p); // ERROR: ambiguous
You can also request explicit conversions using the usual cast notations:
long l = static_cast<int>(p); // convert to int, then to long
g((char)p); // convert to char
How does the compiler deduce , how to call the right overload?
Whenever there's a type mismatch, the compiler looks for a conversion sequence. The rules are quite complicated, but basically the sequence can include at most one user-defined conversion (using either an operator like this, or a converting construction), as well as standard conversions such as int to long.
This is sometimes called the Return Type Resolver idiom or "overload on return type". The conversion operator to call is selected thanks to the context of use where an implicit conversion is needed (for example based on the type of an object to initialize or assign to). For example:
#include <stdio.h>
class RtR {
public:
operator int() const
{
puts("operator int()");
return 42;
}
operator double() const
{
puts("operator double()");
return 3.14;
}
};
void f(int) {}
int main()
{
RtR x;
int i = x; // or int i = RtR();
double d = x;
f(x);
}
output:
operator int()
operator double()
operator int()
See it live.
In 13.1 Overloadable declarations:
Function declarations that differ only in the return type cannot be
overloaded. [ Note: ... It does not apply to sets of functions
fabricated as a result of name lookup (e.g., because of using-directives) or overload resolution (e.g.,
for operator functions) ... ]
Hence this is valid:
struct X {
// Conversion function:
operator int () { return 1; }
operator double () { return 2; }
};
In addition (not relating directly to the question):
struct Y
{
// Operator (Function call):
int operator () (int) { return 1; }
double operator () (double) { return 2; }
// Operator (Subscripting):
int operator [] (int) { return 1; }
double operator [] (double) { return 2; }
// Operator (Shift):
int operator << (int) { return 1; }
double operator << (double) { return 2; }
// and more ...
};
The above code is for operator type conversions and provide an implicit way to cast the Proxy type to int and char.
The compiler "knows" based on the context of the conversion calls, for instance:
Proxy p;
// p_int will be set equal to p.my_owner->getInt()
int p_int = p;
// p_char will be set equal to p.my_owner->getChar()
char p_char = p;
The fact that it's a proxy is irrelevant; the same thing works for any class. Those are conversion operators, and the compiler does select the right version based on how it's used in the calling code.
struct S {
operator int() const { return 1; }
operator double() const { return 2.0; }
};
int main() {
S s;
int i = s;
double d = s;
std::cout << i << ' ' << d << '\n';
return 0;
}
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();
}