Функция пользовательского преобразования
Включает неявное преобразование или явное преобразование из типа класса в другой тип.
Синтаксис
Функция преобразования объявляется как нестатическая член-функция или член-шаблон функции без параметров, без явного типа возврата и с именем следующего формата:
operator conversion-type-id | (1) | |
explicit operator conversion-type-id | (2) | (с C++11) |
explicit ( expression ) operator conversion-type-id | (3) | (с C++20) |
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