Spec-Zone.ru › C++

Функция пользовательского преобразования

Включает неявное преобразование или явное преобразование из типа класса в другой тип.

Синтаксис

Функция преобразования объявляется как нестатическая член-функция или член-шаблон функции без параметров, без явного типа возврата и с именем следующего формата:

operator conversion-type-id (1)
explicit operator conversion-type-id (2) (с C++11)
explicit ( expression ) operator conversion-type-id (3) (с C++20)
1) Объявляет функцию пользовательского преобразования, которая участвует во всех неявных и явных преобразованиях.
2) Объявляет функцию пользовательского преобразования, которая участвует только в прямой инициализации и явных преобразованиях.
3) Объявляет функцию пользовательского преобразования, которая является условно явной.

conversion-type-id — это идентификатор типа, за исключением того, что операторы функций и массивов [] или () не допускаются в его деклараторе (следовательно, преобразование в типы, такие как указатель на массив, требует псевдонима типа/typedef или шаблона тождества: см. ниже). Независимо от typedef, conversion-type-id не может представлять тип массива или функцию.

Хотя тип возврата не допускается в объявлении функции пользовательского преобразования, decl-specifier-seq грамматики объявления может быть присутствовать и может включать любой спецификатор, кроме type-specifier или ключевого слова static, В частности, помимо explicit, также допускаются спецификаторы inline, virtual, constexpr(с C++11), consteval(с C++20) и friend (обратите внимание, что friend требует квалифицированного имени: friend A::operator B();).

Когда такая член-функция объявлена в классе X, она выполняет преобразование из X в conversion-type-id:

struct X
{
    // implicit conversion
    operator int() const { return 7; }
 
    // explicit conversion
    explicit operator int*() const { return nullptr; }
 
    // Error: array operator not allowed in conversion-type-id
//  operator int(*)[3]() const { return nullptr; }
 
    using arr_t = int[3];
    operator arr_t*() const { return nullptr; } // OK if done through typedef
//  operator arr_t () const; // Error: conversion to array not allowed in any case
};
 
int main()
{
    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
 
    int (*pa)[3] = x;  // OK
}

Объяснение

Функция пользовательского преобразования вызывается на второй стадии неявного преобразования, которая состоит из нуля или одной функции-конструктора преобразования или нуля или одной функции пользовательского преобразования.

Если обе функции преобразования и конструкторы преобразования могут быть использованы для выполнения некоторого пользовательского преобразования, функции преобразования и конструкторы рассматриваются при разрешении перегрузки в контексте копирования инициализации и контексте инициализации ссылок, но только конструкторы рассматриваются в контексте прямой инициализации.

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
}

Функция преобразования в собственный (возможно, с квалификатором cv) класс (или ссылку на него), в базовый класс (или ссылку на него) и в тип void может быть определена, но не может быть выполнена как часть последовательности преобразования, за исключением, в некоторых случаях, через виртуальную передачу:

struct D;
 
struct B
{
    virtual operator D() = 0;
};
 
struct D : B
{
    operator D() override { return D(); }
};
 
int main()
{
    D obj;
    D obj2 = obj; // does not call D::operator D()
    B& br = obj;
    D obj3 = br;  // calls D::operator D() through virtual dispatch
}

Она также может быть вызвана с использованием синтаксиса вызова член-функции:

struct B {};
 
struct X : B
{
    operator B&() { return *this; };
};
 
int main()
{
    X x;
    B& b1 = x;                  // does not call X::operatorB&()
    B& b2 = static_cast<B&>(x); // does not call X::operatorB&
    B& b3 = x.operator B&();    // calls X::operatorB&
}

При явном вызове функции преобразования conversion-type-id жадная: она представляет собой самую длинную последовательность токенов, которая могла бы сформировать conversion-type-id (включая атрибуты, если они есть)(с C++11):

& x.operator int * a; // error: parsed as & (x.operator int*) a,
                      //           not as & (x.operator int) * a
 
operator int [[noreturn]] (); // error: noreturn attribute applied to a type

Плейсхолдер auto может использоваться в conversion-type-id, указывая на вывод типа возврата:

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
};

Примечание: функция-шаблон преобразования не допускает вывод типа возврата.

(с C++14)

Функции преобразования могут наследоваться и могут быть виртуальными, но не могут быть статическими. Функция преобразования в производном классе не скрывает функцию преобразования в базовом классе, если они не преобразуют к одному и тому же типу.

Функция преобразования может быть шаблонной член-функцией, например, std::auto_ptr<T>::operator auto_ptr<Y>. См. член-шаблон и вывод аргументов шаблона для применимых специальных правил.

Отчеты об ошибках

Следующие отчеты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применимо к Поведение, как опубликовано Корректное поведение
CWG 296 C++98 функции преобразования могли быть статическими они не могут быть объявлены статическими
CWG 2016 C++98 функции преобразования не могли указывать типы возврата,
но типы присутствовали в conversion-type-id
типы возврата не могут быть указаны в
спецификаторах объявления функций преобразования
CWG 2175 C++11 не было ясно, является ли [[noreturn]] в
operator int [[noreturn]] (); частью
noptr-declarator (декларатора функции) или conversion-type-id
это часть
conversion-type-id

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/cast_operator

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API