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 — это 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

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

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>. Об особых правилах, которые применяются в этом случае, см. разделы шаблон-член и вывод аргументов шаблона.

Ключевые слова

operator

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

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

Отчёт об ошибке Применён к Опубликованное поведение Правильное поведение
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/cpp/language/cast_operator

Spec-Zone.ru

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