Namespaces
Variants

User-defined conversion function

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Permite la conversión implícita o conversión explícita desde un class type a otro tipo.

Contenidos

Sintaxis

La función de conversión se declara como una función miembro no estática o una plantilla de función miembro sin parámetros, sin tipo de retorno explícito, y con el nombre de la forma:

operator conversion-type-id (1)
explicit operator conversion-type-id (2) (desde C++11)
explicit ( expression ) operator conversion-type-id (3) (desde C++20)
1) Declara una función de conversión definida por el usuario que participa en todas las conversiones implícitas y conversiones explícitas .
2) Declara una función de conversión definida por el usuario que participa únicamente en direct-initialization y explicit conversions .
3) Declara una función de conversión definida por el usuario que es condicionalmente explícita .

conversion-type-id es un type-id excepto que los operadores de función y array [] o () no están permitidos en su declarador (por lo tanto, la conversión a tipos como puntero a array requiere un alias de tipo/typedef o una plantilla de identidad: véase más abajo). Independientemente de typedef, conversion-type-id no puede representar un tipo array o un tipo función.

Aunque el tipo de retorno no está permitido en la declaración de una función de conversión definida por el usuario, la decl-specifier-seq de la gramática de declaración puede estar presente y puede incluir cualquier especificador excepto type-specifier o la palabra clave static . En particular, además de explicit , los especificadores inline , virtual , constexpr (desde C++11) , consteval (desde C++20) , y friend también están permitidos (nótese que friend requiere un nombre calificado: friend A :: operator B ( ) ; ).

Cuando dicha función miembro se declara en la clase X, realiza la conversión de X a conversion-type-id :

struct X
{
    // conversión implícita
    operator int() const { return 7; }
    // conversión explícita
    explicit operator int*() const { return nullptr; }
    // Error: operador de array no permitido en conversion-type-id
//  operator int(*)[3]() const { return nullptr; }
    using arr_t = int[3];
    operator arr_t*() const { return nullptr; } // OK si se hace mediante typedef
//  operator arr_t () const; // Error: conversión a array no permitida en ningún caso
};
int main()
{
    X x;
    int n = static_cast<int>(x);   // OK: establece n a 7
    int m = x;                     // OK: establece m a 7
    int* p = static_cast<int*>(x); // OK: establece p a null
//  int* q = x; // Error: no hay conversión implícita
    int (*pa)[3] = x;  // OK
}

Explicación

La función de conversión definida por el usuario se invoca en la segunda etapa de la conversión implícita , que consiste en cero o un constructor de conversión o cero o una función de conversión definida por el usuario.

Si tanto las funciones de conversión como los constructores de conversión pueden utilizarse para realizar alguna conversión definida por el usuario, tanto las funciones de conversión como los constructores son considerados por la resolución de sobrecarga en contextos de inicialización por copia y inicialización por referencia , pero solo los constructores son considerados en contextos de inicialización directa .

struct To
{
    To() = default;
    To(const struct From&) {} // constructor de conversión
};
struct From
{
    operator To() const {return To();} // función de conversión
};
int main()
{
    From f;
    To t1(f);  // inicialización directa: llama al constructor
    // Nota: si el constructor de conversión no está disponible, se seleccionará el constructor de copia implícito
    // y se llamará a la función de conversión para preparar su argumento
//  To t2 = f; // inicialización por copia: ambigua
    // Nota: si la función de conversión es de un tipo no constante, ej.
    // From::operator To();, será seleccionada en lugar del constructor en este caso
    To t3 = static_cast<To>(f); // inicialización directa: llama al constructor
    const To& r = f;            // inicialización de referencia: ambigua
}

La función de conversión a su propia clase (posiblemente calificada cv) (o a una referencia de ella), a la base de su propia clase (o a una referencia de ella), y al tipo void puede definirse, pero no puede ejecutarse como parte de la secuencia de conversión, excepto, en algunos casos, mediante virtual dispatch:

struct D;
struct B
{
    virtual operator D() = 0;
};
struct D : B
{
    operator D() override { return D(); }
};
int main()
{
    D obj;
    D obj2 = obj; // no llama a D::operator D()
    B& br = obj;
    D obj3 = br;  // llama a D::operator D() mediante despacho virtual
}

También se puede llamar usando la sintaxis de llamada a función miembro:

struct B {};
struct X : B
{
    operator B&() { return *this; };
};
int main()
{
    X x;
    B& b1 = x;                  // no llama a X::operatorB&()
    B& b2 = static_cast<B&>(x); // no llama a X::operatorB&
    B& b3 = x.operator B&();    // llama a X::operatorB&
}

Al realizar una llamada explícita a la función de conversión, conversion-type-id es ambicioso: es la secuencia más larga de tokens que podría formar un conversion-type-id (incluyendo atributos, si los hay) (desde C++11) :

& x.operator int * a; // error: interpretado como & (x.operator int*) a,
                      //           no como & (x.operator int) * a
operator int [[noreturn]] (); // error: atributo noreturn aplicado a un tipo

El marcador de posición auto puede utilizarse en conversion-type-id , indicando un tipo de retorno deducido :

struct X
{
    operator int(); // OK
    operator auto() -> short; // error: trailing return type not part of syntax
    operator auto() const { return 10; } // OK: deduced return type
    operator decltype(auto)() const { return 10l; } // OK: deduced return type
};

Nota: una plantilla de función de conversión no puede tener un tipo de retorno deducido.

(desde C++14)

Las funciones de conversión pueden heredarse y pueden ser virtual , pero no pueden ser static . Una función de conversión en la clase derivada no oculta una función de conversión en la clase base a menos que conviertan al mismo tipo.

La función de conversión puede ser una función miembro plantilla, por ejemplo, std::auto_ptr<T>::operator auto_ptr<Y> . Consulte plantilla miembro y deducción de argumentos de plantilla para las reglas especiales aplicables.

Palabras clave

operator

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 296 C++98 las funciones de conversión podían ser estáticas no pueden declararse estáticas
CWG 2016 C++98 las funciones de conversión no podían especificar tipos de retorno,
pero los tipos están presentes en conversion-type-id
los tipos de retorno no pueden especificarse en los
especificadores de declaración de funciones de conversión
CWG 2175 C++11 no estaba claro si el [ [ noreturn ] ] en
operator int [ [ noreturn ] ] ( ) ; se analiza como parte de
noptr-declarator (del declarador de función) o de conversion-type-id
se analiza como parte de
conversion-type-id