Files
2025-10-25 03:02:53 +03:00

255 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[class.conv]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.conv)
### 11.4.8 Conversions [class.conv]
#### [11.4.8.1](#general) General [[class.conv.general]](class.conv.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2441)
Type conversions of class objects can be specified by constructors and
by conversion functions[.](#general-1.sentence-1)
These conversions are called[*user-defined conversions*](#def:conversion,user-defined "11.4.8.1General[class.conv.general]") and are used for implicit type conversions ([[conv]](conv "7.3Standard conversions")),
for initialization ([[dcl.init]](dcl.init "9.5Initializers")),
and for explicit type conversions ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"))[.](#general-1.sentence-2)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2455)
User-defined conversions are applied only where they are unambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"), [[class.conv.fct]](#fct "11.4.8.3Conversion functions"))[.](#general-2.sentence-1)
Conversions obey the access control rules ([[class.access]](class.access "11.8Member access control"))[.](#general-2.sentence-2)
Access control is applied after ambiguity resolution ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#general-2.sentence-3)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2460)
[*Note [1](#general-note-1)*:
See [[over.match]](over.match "12.2Overload resolution") for a discussion of the use of conversions in function calls[.](#general-3.sentence-1)
— *end note*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2465)
At most one user-defined conversion (constructor or conversion function)
is implicitly applied to a single value[.](#general-4.sentence-1)
[*Example [1](#general-example-1)*: struct X {operator int();};
struct Y {operator X();};
Y a;int b = a; // error: no viable conversion (a.operator X().operator int() not considered)int c = X(a); // OK, a.operator X().operator int() — *end example*]
#### [11.4.8.2](#ctor) Conversion by constructor [[class.conv.ctor]](class.conv.ctor)
[1](#ctor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2488)
A constructor that is not explicit ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers"))
specifies a conversion from
the types of its parameters (if any)
to the type of its class[.](#ctor-1.sentence-1)
[*Example [1](#ctor-example-1)*:
[🔗](#:Jessie)
struct X { X(int);
X(const char*, int = 0);
X(int, int);};
void f(X arg) { X a = 1; // a = X(1) X b = "Jessie"; // b = X("Jessie",0) a = 2; // a = X(2) f(3); // f(X(3)) f({1, 2}); // f(X(1,2))} — *end example*]
[2](#ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2512)
[*Note [1](#ctor-note-1)*:
An explicit constructor constructs objects just like non-explicit
constructors, but does so only where the direct-initialization syntax ([[dcl.init]](dcl.init "9.5Initializers"))
or where casts ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")) are explicitly
used; see also [[over.match.copy]](over.match.copy "12.2.2.5Copy-initialization of class by user-defined conversion")[.](#ctor-2.sentence-1)
A default constructor can be an explicit constructor; such a constructor
will be used to perform default-initialization
or value-initialization ([[dcl.init]](dcl.init "9.5Initializers"))[.](#ctor-2.sentence-2)
[*Example [2](#ctor-example-2)*: struct Z {explicit Z(); explicit Z(int); explicit Z(int, int);};
Z a; // OK, default-initialization performed Z b{}; // OK, direct initialization syntax used Z c = {}; // error: copy-list-initialization Z a1 = 1; // error: no implicit conversion Z a3 = Z(1); // OK, direct initialization syntax used Z a2(1); // OK, direct initialization syntax used Z* p = new Z(1); // OK, direct initialization syntax used Z a4 = (Z)1; // OK, explicit cast used Z a5 = static_cast<Z>(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion — *end example*]
— *end note*]
#### [11.4.8.3](#fct) Conversion functions [[class.conv.fct]](class.conv.fct)
[conversion-function-id:](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")
operator [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")
[conversion-type-id:](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")opt
[conversion-declarator:](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")opt
[1](#fct-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2563)
A declaration
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") has
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") that is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") declares a [*conversion function*](#def:function,conversion "11.4.8.3Conversion functions[class.conv.fct]");
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall be
a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the form
[*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1General[dcl.decl.general]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
where the [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1General[dcl.decl.general]") consists solely of
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"),
an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), and
optional surrounding parentheses, and
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") has one of the following forms:
- [(1.1)](#fct-1.1)
in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") that belongs to
the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of a class or class template
but is not a friend declaration ([[class.friend]](class.friend "11.8.4Friends")),
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]");
- [(1.2)](#fct-1.2)
otherwise, the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")[.](#fct-1.sentence-1)
[2](#fct-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2589)
A conversion function shall have no non-object parameters and
shall be a non-static member function of a class or class template X;
its declared return type is the [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") and
it specifies a conversion from X to
the type specified by the [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]"),
interpreted as a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ([[dcl.name]](dcl.name "9.3.2Type names"))[.](#fct-2.sentence-1)
A [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a conversion function (if any) shall not be
a [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")[.](#fct-2.sentence-2)
[3](#fct-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2600)
[*Note [1](#fct-note-1)*:
A conversion function is never invoked for
implicit or explicit conversions of an object
to the same object type (or a reference to it),
to a base class of that type (or a reference to it),
or to cv void[.](#fct-3.sentence-1)
Even though never directly called to perform a conversion,
such conversion functions can be declared and can potentially
be reached through a call to a virtual conversion function in a base class[.](#fct-3.sentence-2)
— *end note*]
[*Example [1](#fct-example-1)*: struct X {operator int(); operator auto() -> short; // error: trailing return type};
void f(X a) {int i = int(a);
i = (int)a;
i = a;}
In all three cases the value assigned will be converted byX::operator int()[.](#fct-3.sentence-3)
— *end example*]
[4](#fct-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2628)
A conversion function may be explicit ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers")), in which case it is only considered as a user-defined conversion for direct-initialization ([[dcl.init]](dcl.init "9.5Initializers"))[.](#fct-4.sentence-1)
Otherwise, user-defined conversions are not restricted to use in assignments and initializations[.](#fct-4.sentence-2)
[*Example [2](#fct-example-2)*: class Y { };struct Z {explicit operator Y() const;};
void h(Z z) { Y y1(z); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization Y y3 = (Y)z; // OK, cast notation}void g(X a, X b) {int i = (a) ? 1+a : 0; int j = (a&&b) ? a+b : i; if (a) {}} — *end example*]
[5](#fct-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2652)
The[*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") shall not represent a function type nor an array type[.](#fct-5.sentence-1)
The[*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") in a[*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") is the longest sequence of
tokens that could possibly form a [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")[.](#fct-5.sentence-2)
[*Note [2](#fct-note-2)*:
This prevents ambiguities between the declarator operator * and its expression
counterparts[.](#fct-5.sentence-3)
[*Example [3](#fct-example-3)*: &ac.operator int*i; // syntax error:// parsed as: &(ac.operator int *)i// not as: &(ac.operator int)*i
The * is the pointer declarator and not the multiplication operator[.](#fct-5.sentence-4)
— *end example*]
This rule also prevents ambiguities for attributes[.](#fct-5.sentence-5)
[*Example [4](#fct-example-4)*: operator int [[noreturn]] (); // error: noreturn attribute applied to a type — *end example*]
— *end note*]
[6](#fct-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2681)
[*Note [3](#fct-note-3)*:
A conversion function in a derived class hides only
conversion functions in base classes that convert to the same type[.](#fct-6.sentence-1)
A conversion function template with a dependent return type hides only
templates in base classes that correspond to it ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"));
otherwise, it hides and is hidden as a non-template function[.](#fct-6.sentence-2)
Function overload resolution ([[over.match.best]](over.match.best "12.2.4Best viable function")) selects
the best conversion function to perform the conversion[.](#fct-6.sentence-3)
[*Example [5](#fct-example-5)*: struct X {operator int();};
struct Y : X {operator char();};
void f(Y& a) {if (a) { // error: ambiguous between X::operator int() and Y::operator char()}} — *end example*]
— *end note*]
[7](#fct-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2709)
Conversion functions can be virtual[.](#fct-7.sentence-1)
[8](#fct-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2713)
A conversion function template shall not have a
deduced return type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))[.](#fct-8.sentence-1)
[*Example [6](#fct-example-6)*: struct S {operator auto() const { return 10; } // OKtemplate<class T>operator auto() const { return 1.2; } // error: conversion function template}; — *end example*]