'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.
Related
In the class below,
Why would you make the operators explicit. I thought that explicit was to prevent implicit calling of constructors?
class Content
{
public:
virtual ~Content() = 0;
virtual explicit operator float&();
virtual explicit operator long long&();
virtual explicit operator std::string&()
}
I thought that explicit was to prevent implicit calling of
constructors?
Since C++11 it also applies to user-defined conversions (a.k.a. the cast operator).
Why would you make the operators explicit
Used in this context, the explicit keyword makes the conversion eligible only for direct-initialization and explicit conversions. See here under [class.conv.fct¶2]:
A conversion function may be explicit ([dcl.fct.spec]), in which case
it is only considered as a user-defined conversion for
direct-initialization ([dcl.init]). Otherwise, user-defined
conversions are not restricted to use in assignments and
initializations.
This aids you in making sure the compiler doesn't try the conversion against your intention, so that you have to explicitly cast it yourself, leaving less room for error. Example:
struct Foo
{
explicit operator int() {return 0;}
operator int*() {return nullptr;}
};
int main()
{
Foo foo;
//int xi = foo; // Error, conversion must be explicit
int i = static_cast<int>(foo); // OK, conversion is explicit
int* i_ptr = foo; // OK, implicit conversion to `int*` is allowed
int i_direct(foo); // OK, direct initialization allowed
int* i_ptr_direct(foo); // OK, direct initialization after implicit conversion
return 0;
}
It can also help resolve ambiguity in cases where multiple conversion options apply, leaving the compiler without a criteria for deciding which one to choose:
struct Bar
{
operator int() {return 1;}
operator char() {return '1';}
};
int main()
{
Bar bar;
//double d = bar; // Error, implicit conversion is ambiguous
return 0;
}
Add explicit:
struct Bar
{
operator int() {return 1;}
explicit operator char() {return '1';}
};
int main()
{
Bar bar;
double d = bar; // OK, implicit conversion to `int` is the only option
return 0;
}
Consider the following:
struct Content
{
operator float() { return 42.f; }
friend Content operator+(Content& lhs, float) { return lhs; }
};
int main()
{
Content c{};
c + 0; // error: ambiguous overload for 'operator+'
}
Here, the compiler cannot choose between operator+(Content&, float) and operator+(float, int). Making the float operator explicit resolves this ambiguity*:
c + 0; // operator+(Content&, float)
or
static_cast<float>(c) + 0; // operator+(float, int)
*) provided it makes sense to prefer one over the other.
The other answers cover how it works, but I think you should be told why it was added to C++.
A smart pointer usually has a conversion to bool so you can do this:
std::shared_ptr<int> foo;
if (foo) {
*foo = 7;
}
where if(foo) converts foo to bool. Unfortunately:
int x = foo+2;
converts foo to bool, then to int, then adds 2. This is almost always a bug. This is permitted because while only one user defined conversion is done, a user defined conversion followed by a built in conversion can silently occur.
To fix this programmers would do crazy things like add:
struct secret {
void unused();
};
struct smart_ptr {
using secret_mem_ptr = void(secret::*)();
operator secret_mem_ptr() const { return 0; }
};
and secret_mem_ptr is a secret pointer to member. A pointer to member has a built in conversion to bool, so:
smart_ptr ptr;
if (!ptr) {
}
"works" -- ptr is convert to secret_mem_ptr, which then is convered to bool, which is then used to decide which branch to take.
This was more than a bit of a hack.
They added explicit on conversion operators to solve this exact problem.
Now:
struct smart_ptr {
explicit operator bool() const { return true; }
};
doesn't permit:
smart_ptr ptr;
int x = 3 + ptr;
but it does permit:
if (ptr) {
}
because the rules were hand-crafted to support exactly that use case. It also doesn't permit:
bool test() {
smart_ptr ptr;
return ptr;
}
here, you have to type:
bool test() {
smart_ptr ptr;
return (bool)ptr;
}
where you explicitly convert ptr to bool.
(I am usually really against C-style casts; I make an exception in the case of (bool)).
You would use it if you wanted a Content object never to be implicitly converted to (say) a float. This could happen in the following way:
void f( float f );
....
Content c;
f( c ); // conversion from Content to float
Without the explicit qualifier, the conversion happens implicitly; with it, you get a compilation error.
Silent, implicit conversions can be the source of a lot of confusion and/or bugs, so it's generally better to make the operators explicit , or probably better yet to provide named functions, such as ToFloat, which tell the reader exactly what is going on.
I am trying to implement a hack where I am trying to overload return. I will let the code talk.
namespace tcn
{
class foo
{
std::string blah;
public:
class proxy
{
int intval;
std::string strval;
public:
proxy(int intv, std::string strv) : intval(intv), strval(strv) {};
operator int() const { return intval; }
operator std::string() const { return strval; }
};
foo();
~foo();
proxy get();
};
foo::foo()
{
// Create stuff //
}
foo::~foo()
{
// Destroy stuff //
}
foo::proxy foo::get()
{
int intval = 911;
std::string strval = "Hello!?";
proxy temp(intval, strval);
return temp;
}
}
int main()
{
tcn::foo bar;
std::string ts = bar.get(); // OK
int ti = bar.get(); // OK
ti = bar.get(); // OK
ts = bar.get(); // Compile error here
return 0;
}
If I try to compile the code it gives an error like following
error: ambiguous overload for 'operator=' (operand types are
'std::string {aka std::basic_string}' and 'tcn::foo::proxy')
ts = bar.get();
I was wondering how to overcome this. I have seen other ways to implement this by using 'hints' ,But am trying to give an easy interface to the user. So I am looking for a simple assignment from the user side. How else could this be implemented?
Thank you in advance and if this looks lame- I apologize. I am no that good in C++.
The call is ambiguous because std::string::operator= has overloads taking std::string and char. Both of these can be called using a tcn::proxy: the first using the std::string conversion operator, and the second using the int conversion operator followed by an integral conversion.
Usually overload resolution would prefer the implicit conversion sequence with no necessary standard conversions over the one requiring an integral conversion, but this choice is only considered if the two conversion sequences go through the same function. Since you have two separate paths going through two different functions, the call is ambiguous.
The solution is to not use integral conversions for things like that; it just leads to weird edge cases, surprising behaviour and hidden bugs.
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;
}
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 want to cast a custom class to a string which compiles in VS2005 very well. But in VS2012 I get the compiler error error C2440: 'type cast' : cannot convert from 'A' to 'std::string'. What do I have to change? This is my example:
#include <string>
using namespace std;
class A
{
public:
A& operator=(const char* c);
operator string ();
operator const char* ();
private:
string value;
};
A::operator string () { return string((const char*)(*this)); }
A& A::operator = (const char* aValue) { value = aValue; return *this; }
A::operator const char *() { const char* wort = "Hello"; return wort; }
int main()
{
A a;
string s = (string)a; // C2440
}
The problem is that there are two possible explicit conversions from A to string - via the conversion operator to string; or via the conversion operator to const char *, then via the conversion constructor to string.
Simply making the conversion implicit will resolve the ambiguity; the second conversion requires two user-defined conversions, and so cannot be chosen for an implicit conversion:
string s = a;
However, the class is still a bit flaky, since sometimes you might need an explicit conversion. I would consider removing at least one of the implicit conversion operators - perhaps replace them with explicit operators (if your compiler supports such things), or with named functions (like string itself does with c_str()).
The conversion is ambiguous.
Stay away from C style casts, and prefer to make the conversions explicit.
#include <string>
using namespace std;
class A
{
public:
A& operator=(const char* c);
explicit operator string ();
explicit operator const char* ();
private:
string value;
};
A::operator string () { return string(static_cast<const char*>(*this)); }
A& A::operator = (const char* aValue) { value = aValue; return *this; }
A::operator const char *() { const char* wort = "Hello"; return wort; }
int main()
{
A a;
string s = static_cast<std::string>(a);
}
Your two conversion operators step on each others toes. Each of them works for implicit conversions. But an explicit cast is like a direct constructor call. In your code
string s = (string)a;
is equivalent to
string s = static_cast<string>(a);
which transforms to something like
string tmp(a);
string s(std::move(tmp)); // this move can be elided
// lifetime of tmp ends here
The crux is the direct initialization string tmp(a). There are two viable string constructors: string(const string&) and explicit string(const char *) and your two conversions allow calling either. As neither conversion sequence is better, the call is ambiguous.
By the way, the version using copy initialization without explicit cast is not ambiguous:
string s = a;
should work. Depending on that is very brittle, so not recommended.
You should make your conversion operators explicit (if you are using C++11) or drop one of them.