Files
cppdraft_translate/cppdraft/class/conv.md
2025-10-25 03:02:53 +03:00

14 KiB
Raw Blame History

[class.conv]

11 Classes [class]

11.4 Class members [class.mem]

11.4.8 Conversions [class.conv]

11.4.8.1 General [class.conv.general]

1

#

Type conversions of class objects can be specified by constructors and by conversion functions.

These conversions are calleduser-defined conversions and are used for implicit type conversions ([conv]), for initialization ([dcl.init]), and for explicit type conversions ([expr.type.conv], [expr.cast], [expr.static.cast]).

2

#

User-defined conversions are applied only where they are unambiguous ([class.member.lookup], [class.conv.fct]).

Conversions obey the access control rules ([class.access]).

Access control is applied after ambiguity resolution ([basic.lookup]).

3

#

[Note 1:

See [over.match] for a discussion of the use of conversions in function calls.

— end note]

4

#

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

[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 Conversion by constructor [class.conv.ctor]

1

#

A constructor that is not explicit ([dcl.fct.spec]) specifies a conversion from the types of its parameters (if any) to the type of its class.

[Example 1:

🔗

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

#

[Note 1:

An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax ([dcl.init]) or where casts ([expr.static.cast], [expr.cast]) are explicitly used; see also [over.match.copy].

A default constructor can be an explicit constructor; such a constructor will be used to perform default-initialization or value-initialization ([dcl.init]).

[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(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion — end example]

— end note]

11.4.8.3 Conversion functions [class.conv.fct]

conversion-function-id:
operator conversion-type-id

conversion-type-id:
type-specifier-seq conversion-declaratoropt

conversion-declarator:
ptr-operator conversion-declaratoropt

1

#

A declaration whose declarator-id has an unqualified-id that is a conversion-function-id declares a conversion function; its declarator shall be a function declarator ([dcl.fct]) of the form

noptr-declarator parameters-and-qualifiers

where the noptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:

in a member-declaration that belongs to the member-specification of a class or class template but is not a friend declaration ([class.friend]), the id-expression is a conversion-function-id;

otherwise, the id-expression is a qualified-id whose unqualified-id is a conversion-function-id.

2

#

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 and it specifies a conversion from X to the type specified by the conversion-type-id, interpreted as a type-id ([dcl.name]).

A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall not be a defining-type-specifier.

3

#

[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.

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.

— end note]

[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().

— end example]

4

#

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.

[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

#

Theconversion-type-id shall not represent a function type nor an array type.

Theconversion-type-id in aconversion-function-id is the longest sequence of tokens that could possibly form a conversion-type-id.

[Note 2:

This prevents ambiguities between the declarator operator * and its expression counterparts.

[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.

— end example]

This rule also prevents ambiguities for attributes.

[Example 4: operator int noreturn (); // error: noreturn attribute applied to a type — end example]

— end note]

6

#

[Note 3:

A conversion function in a derived class hides only conversion functions in base classes that convert to the same type.

A conversion function template with a dependent return type hides only templates in base classes that correspond to it ([class.member.lookup]); otherwise, it hides and is hidden as a non-template function.

Function overload resolution ([over.match.best]) selects the best conversion function to perform the conversion.

[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

#

Conversion functions can be virtual.

8

#

A conversion function template shall not have a deduced return type ([dcl.spec.auto]).

[Example 6: struct S {operator auto() const { return 10; } // OKtemplateoperator auto() const { return 1.2; } // error: conversion function template}; — end example]