16 Overloading [over]

16.5 Overloaded operators [over.oper]

Объявление функции, имеющее одно из следующих operator-function-ids названий, объявляет operator function. Объявление шаблона функции, имеющее одно из следующих operator-function-ids названий, объявляетoperator function template. Специализация шаблона операторной функции также является операторной функцией. Операторная функция называется implement оператором, указанным в его operator-function-id.

operator-function-id:
	operator operator
operator: one of
	new	delete	new[]	delete[]
	+	-	*	/	%	^	&	|	~
	!	=	<	>	+=	-=	*=	/=	%=
	^=	&=	|=	<<	>>	>>=	<<=	==	!=
	<=	>=	&&	||	++	--	,	->*	->
	()	[]

[ Note: Последние два оператора -function call иsubscripting. Операторы new[], delete[], ()и [] образуются из более чем одного маркеров. ] end note

И унарная, и бинарная формы

+    -    *     &

может быть перегружен.

Следующие операторы не могут быть перегружены:

.    .*   ::    ?:

также нельзя использовать символы предварительной обработки # и ## (пункт[cpp]).

Операторные функции обычно не вызываются напрямую; вместо этого они вызываются для оценки реализуемых ими операторов ([over.unary] -[over.inc]). Однако их можно вызвать явно, используя в operator-function-id качестве имени функции в синтаксисе вызова функции ([expr.call]). [Example:

complex z = a.operator+(b);     // complex z = a+b;
void* p = operator new(sizeof(int)*n);

end example]

Функции распределения и освобождения, operator new, operator new[], operator delete и operator delete​[], описаны полностью[basic.stc.dynamic]. Атрибуты и ограничения, найденные в остальной части этого подпункта, не применяются к ним, если явно не указано в[basic.stc.dynamic].

Операторная функция должна быть либо нестатической функцией-членом, либо функцией, не являющейся членом, которая имеет по крайней мере один параметр, тип которого является классом, ссылкой на класс, перечислением или ссылкой на перечисление. Невозможно изменить приоритет, группировку или количество операндов операторов. Значение операторов =(унарный) &и , (запятая), предопределенных для каждого типа, можно изменить для конкретных классов и типов перечисления, определив операторные функции, которые реализуют эти операторы. Операторные функции наследуются так же, как и другие функции базового класса.

Тождества между некоторыми предопределенными операторами, применяемыми к базовым типам (например, ++a a+=1), не обязательно должны сохраняться для операторных функций. Некоторые предопределенные операторы, например +=, требуют, чтобы операнд был lvalue при применении к базовым типам; это не требуется для операторных функций.

Операторная функция не может иметьdefault arguments, за исключением случаев, явно указанных ниже. Функции оператора не могут иметь больше или меньше параметров, чем число, необходимое для соответствующего оператора, как описано в оставшейся части этого подпункта.

Операторы не упоминается явно в подразделах[over.ass] через[over.inc] действуют как обычные одинарные и бинарные операторы подчиняясь правилам[over.unary] или[over.binary].

16.5.1 Unary operators [over.unary]

Префиксный унарный оператор должен быть реализован нестатической функцией-членом ([class.mfct]) без параметров или функцией, не являющейся членом, с одним параметром. Таким образом, для любого одноместной операции префикса @, @x может быть интерпретирована как либо x.operator@() или operator@(x). Если были объявлены обе формы операторной функции, правила[over.match.oper] определяют, какая интерпретация используется, если таковая имеется. См.[over.inc] Объяснение постфиксных унарных операторов ++ и --.

Считается, что унарная и двоичная формы одного и того же оператора имеют одно и то же имя. [ Note: Следовательно, унарный оператор может скрыть бинарный оператор из охватывающей области, и наоборот. ]end note

16.5.2 Binary operators [over.binary]

Бинарный оператор должен быть реализован либо нестатической функцией-членом ([class.mfct]) с одним параметром, либо функцией, не являющейся членом, с двумя параметрами. Таким образом, для любого бинарного оператора @, x@y может быть интерпретирована как либо x.operator@(y) или operator@(x,y). Если были объявлены обе формы операторной функции, правила[over.match.oper] определяют, какая интерпретация используется, если таковая имеется.

16.5.3 Assignment [over.ass]

Оператор присваивания должен быть реализован нестатической функцией-членом с ровно одним параметром. Поскольку оператор присваивания копии operator= неявно объявляется для класса, если он не объявлен пользователем ([class.copy]), оператор присваивания базового класса всегда скрывается оператором присваивания копии производного класса.

Любой оператор присваивания, даже операторы присваивания копирования и перемещения, могут быть виртуальными. [ Note: Для производного класса D с базовым классом, B для которого было объявлено виртуальное назначение копирования / перемещения, оператор назначения копирования / перемещения в D не отменяет Bвиртуальный оператор назначения копирования / перемещения. [Example:

struct B {
  virtual int operator= (int);
  virtual B& operator= (const B&);
};
struct D : B {
  virtual int operator= (int);
  virtual D& operator= (const B&);
};

D dobj1;
D dobj2;
B* bptr = &dobj1;
void f() {
  bptr->operator=(99);          // calls D​::​operator=(int)
  *bptr = 99;                   // ditto
  bptr->operator=(dobj2);       // calls D​::​operator=(const B&)
  *bptr = dobj2;                // ditto
  dobj1 = dobj2;                // calls implicitly-declared D​::​operator=(const D&)
}

end example] ]end note

16.5.4 Function call [over.call]

operator() должна быть нестатической функцией-членом с произвольным числом параметров. У него могут быть аргументы по умолчанию. Он реализует синтаксис вызова функции

postfix-expression ( expression-listopt )

где postfix-expression оценивается как объект класса, а возможно пустое значение expression-list соответствует списку параметров operator() функции-члена класса. Таким образом, вызов x(arg1,...) интерпретируется как x.operator()(arg1, ...) объект класса x типа, T если он T​::​operator()(T1, T2, T3) существует, и если оператор выбран как функция наилучшего соответствия механизмом разрешения перегрузки ([over.match.best]).

16.5.5 Subscripting [over.sub]

operator[] должен быть нестатической функцией-членом с одним параметром. Он реализует синтаксис индексации

postfix-expression [ expr-or-braced-init-list ]

Таким образом, индексирующее выражение x[y] интерпретируется как x.operator[](y) объект класса x типа, T если он T​::​operator[](T1) существует и если оператор выбран как функция наилучшего соответствия механизмом разрешения перегрузки ([over.match.best]). [Example:

struct X {
  Z operator[](std::initializer_list<int>);
};
X x;
x[{1,2,3}] = 7;           // OK: meaning x.operator[]({1,2,3})
int a[10];
a[{1,2,3}] = 7;           // error: built-in subscript operator

end example]

16.5.6 Class member access [over.ref]

operator-> должна быть нестатической функцией-членом, не имеющей параметров. Он реализует синтаксис доступа к членам класса, который использует->.

postfix-expression -> templateopt id-expression
postfix-expression -> pseudo-destructor-name

Выражение x->m интерпретируется как (x.operator->())->m объект класса x типа, T если он T​::​operator->() существует и если оператор выбран как функция наилучшего соответствия механизмом разрешения перегрузки ([over.match]).

16.5.7 Increment and decrement [over.inc]

Вызываемая пользователем функция operator++ реализует префиксный и постфиксный ++ оператор. Если эта функция является нестатической функцией-членом без параметров или функцией-членом с одним параметром, она определяет оператор приращения префикса ++ для объектов этого типа. Если функция является нестатической функцией-членом с одним параметром (который должен иметь тип int) или функцией, не являющейся членом, с двумя параметрами (второй из которых должен иметь тип int), она определяет оператор постфиксного приращения ++ для объектов этого типа. тип. Когда постфиксное приращение вызывается в результате использования ++ оператора, int аргумент будет иметь нулевое значение.134 [Example:

struct X {
  X&   operator++();            // prefix ++a
  X    operator++(int);         // postfix a++
};

struct Y { };
Y&   operator++(Y&);            // prefix ++b
Y    operator++(Y&, int);       // postfix b++

void f(X a, Y b) {
  ++a;                          // a.operator++();
  a++;                          // a.operator++(0);
  ++b;                          // operator++(b);
  b++;                          // operator++(b, 0);

  a.operator++();               // explicit call: like ++a;
  a.operator++(0);              // explicit call: like a++;
  operator++(b);                // explicit call: like ++b;
  operator++(b, 0);             // explicit call: like b++;
}

end example]

Операторы префиксного и постфиксного декремента -- обрабатываются аналогично.

operator++ Явный вызов , как в выражениях вроде a.operator++(2), не имеет особых свойств: аргумент для operator++ is 2.

16.5.8 User-defined literals [over.literal]

literal-operator-id:
	operator string-literal identifier
	operator user-defined-string-literal

В string-literalили user-defined-string-literal в a literal-operator-idне должно быть encoding-prefixи не должно быть никаких символов, кроме неявного завершения'\0'. ud-suffixИз user-defined-string-literalили identifierв literal-operator-idназывается literal suffix identifier. Некоторые буквальные идентификаторы суффиксов зарезервированы для будущей стандартизации; см[usrlit.suffix]. Объявление, в котором literal-operator-idиспользуется такой буквальный идентификатор суффикса, неправильно сформировано, диагностика не требуется.

Объявление, имеющее значение declarator-ida, literal-operator-idдолжно быть объявлением функции или шаблона функции в области пространства имен (это может бытьfriend function), явным экземпляром или специализацией шаблона функции или файлом using-declaration. Функция, объявленная с a, literal-operator-id- этоliteral operator. Шаблон функции, объявленный с помощью a, literal-operator-id - этоliteral operator template.

Объявление буквального оператора должно иметь parameter-declaration-clauseэквивалент одного из следующих:

const char*
unsigned long long int
long double
char
wchar_t
char16_t
char32_t
const char*, std::size_t
const wchar_t*, std::size_t
const char16_t*, std::size_t
const char32_t*, std::size_t

Если у параметра естьdefault argument, программа имеет неправильный формат.

Araw literal operator - это буквальный оператор с одним параметром типаconst char*.

Объявление шаблона литерального оператора должно иметь пустое значение, parameter-declaration-clauseа в нем template-parameter-listдолжен быть единственный шаблон, не являющийся template-parameterшаблоном типа parameter pack с типом элементаchar.

Литеральные операторы и шаблоны буквальных операторов не должны иметь привязки к языку C.

[ Note: Литеральные операторы и шаблоны буквальных операторов обычно неявно вызываются черезuser-defined literals. Однако, за исключением ограничений, описанных выше, они являются обычными функциями области пространства имен и шаблонами функций. В частности, они выглядят как обычные функции и шаблоны функций и следуют тем же правилам разрешения перегрузки. Кроме того, они могут быть объявленыinline илиconstexprмогут иметь внутреннюю или внешнюю связь, могут вызываться явно, их адреса могут быть взяты и т. Д. ]end note

[Example:

void operator "" _km(long double);                  // OK
string operator "" _i18n(const char*, std::size_t); // OK
template <char...> double operator "" _\u03C0();    // OK: UCN for lowercase pi
float operator ""_e(const char*);                   // OK
float operator ""E(const char*);                    // error: reserved literal suffix ([usrlit.suffix], [lex.ext])
double operator""_Bq(long double);                  // OK: does not use the reserved identifier _­Bq ([lex.name])
double operator"" _Bq(long double);                 // uses the reserved identifier _­Bq ([lex.name])
float operator " " B(const char*);                  // error: non-empty string-literal
string operator "" 5X(const char*, std::size_t);    // error: invalid literal suffix identifier
double operator "" _miles(double);                  // error: invalid parameter-declaration-clause
template <char...> int operator "" _j(const char*); // error: invalid parameter-declaration-clause
extern "C" void operator "" _m(long double);        // error: C language linkage

end example]