Difference between revisions of "cpp/language/cast operator"
D41D8CD98F (Talk | contribs) m |
D41D8CD98F (Talk | contribs) (§ 12.3.2 in all standards said "The conversion-type-id shall not represent a function type nor an array type.") |
||
Line 12: | Line 12: | ||
@2@ Declares a user-defined conversion function that participates in {{rlp|direct_initialization|direct-initialization}} and explicit conversions only. | @2@ Declares a user-defined conversion function that participates in {{rlp|direct_initialization|direct-initialization}} and explicit conversions only. | ||
{{par begin}} | {{par begin}} | ||
− | {{par | {{spar|conversion-type-id}} | any {{rlp|type#Type naming|type-id}} except | + | {{par | {{spar|conversion-type-id}} | any {{rlp|type#Type naming|type-id}} except those representing a function or an array type}} |
{{par end}} | {{par end}} | ||
Revision as of 02:33, 4 January 2014
Enables implicit conversion from a class type to another type.
Syntax
Conversion function is declared like a non-static member function or member function template with no return type and with the name of the form:
operator conversion-type-id
|
(1) | ||||||||
explicit operator conversion-type-id
|
(2) | (since C++11) | |||||||
conversion-type-id | - | any type-id except those representing a function or an array type |
When such member function is declared in class X, it performs conversion from X to conversion-type-id:
struct X { //implicit conversion operator int() const { return 1; } // explicit conversion explicit operator int*() const { return nullptr; } // Error: array operator not allowed in conversion-type-id // operator int(*)[3]() const { return nullptr; } using ptr_t = int(*)[3]; operator ptr_t() const { return nullptr; } // OK if done through typedef }; X x; int n = static_cast<int>(x); // OK: sets n to 7 int m = x; // OK: sets m to 7 int* p = static_cast<int*>(x); // OK: sets p to null int* q = x; // Error: no implicit conversion
Explanation
User-defined conversion function is invoked on the second stage of the implicit conversion, which consists of zero or one single-argument (converting) constructor or zero or one user-defined conversion function.
If both conversion functions and converting constructors can be used to perform some user-defined conversion, the conversion functions and constructors are both considered by overload resolution in copy-initialization and reference-initialization contexts, but only the constructors are considered in direct-initialization contexts.
struct To { To() = default; To(const struct From&) {} // converting constructor }; struct From { operator To() const {return To();} // conversion function }; int main() { From f; To t1(f); // direct-initialization: calls the constructor // (note, if converting constructor is not available, implicit copy constructor // will be selected, and conversion function will be called to prepare its argument) To t2 = f; // copy-initialization: ambiguous // (note, if conversion function is from a non-const type, e.g. // From::operator To();, it will be selected instead of the ctor in this case) To t3 = static_cast<To>(f); // direct-initialization: calls the constructor const To& r = f; // reference-initialization: ambiguous }
Conversion function to its own (possibly cv-qualified) class (or to a reference to it), to the base of its own class (or to a reference to it), and to the type void can be defined, but can never be executed as part of the conversion sequence (it can still be called using member function call syntax or, in some cases, by virtual dispatch from a conversion sequence)
struct B {}; struct X : B { operator B&() { return *this; }; }; int main() { X x; B& b1 = x; // does not call the user-defined conversion B& b2 = static_cast<B&>(x); // does not call the user-defined conversion B& b3 = x.operator B&(); // calls the user-defined conversion }
When making an explicit call to the conversion function, the type-id is greedy: it is the longest possible sequence of tokens that is a valid type id:
& x.operator int * a; // parsed as & (x.operator int*) a // not as & (x.operator int) * a
Conversion functions can be inherited and can be virtual, but cannot be static. A conversion function in the derived class does not hide a conversion function in the base class unless they are converting to the same type.
Conversion function can be a template member function, for example, std::auto_ptr<T>::operator auto_ptr<Y>