Разрешено ли перегрузить оператор + для стандартного библиотечного типа и встроенного типа?

Разрешено ли перегрузить операторы, такие как operator+ для комбинации стандартного типа библиотеки и встроенного типа, когда такой перегрузки не существует?

Например, допустимо ли реализовывать следующий оператор в пространстве имен по умолчанию или в пользовательском пространстве имен:

std::string operator+(const std::string& s, int right) { ... }

Я знаю, что существуют разные ограничения для реализации вещей в std:: namespace, но мне не ясно, есть ли какое-либо правило против вышеизложенного (является ли это хорошей идеей, конечно, совсем другое дело!).

3

Решение

Например, допустимо ли реализовывать следующий оператор в пространстве имен по умолчанию или в пользовательском пространстве имен:

std::string operator+(const std::string& s, int right) { ... }

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

Там нет ничего, что мешает вам написать что-то вроде:

namespace N {
std::string operator+(std::string s, int ) { return s; }
}

Это хорошо продуманная программа, согласно стандарту. Однако обратите внимание, что, поскольку по определению ваши операторы не будут иметь никаких программно-определенных типов, они никогда не будут найдены ADL. Так как они являются операторами, которые обычно находятся в ADL, это само по себе может быть причиной, чтобы избежать такой схемы:

namespace U {
auto foo() {
return "hello"s + 1; // error: name lookup doesn't find our operator
}

auto bar() {
using namespace N;
return "hello"s + 1; // ok: for some definition of ok
}
}
2

Другие решения

Это нормально, чтобы перегрузить operator+ между std::string а также int, Единственное ограничение, которое стандарт устанавливает на это (https://timsong-cpp.github.io/cppwp/n3337/over.oper#6):

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

Нет никаких ограничений на возможность определять их в вашем пространстве имен даже для типов из стандартной библиотеки.

3

Это законно, чтобы написать это. Но это не обязательно будет делать то, что вы хотите.

Если ваша цель состоит в том, чтобы сделать some_string + 4 легальный код C ++, то его законность будет зависеть от того, где именно появится это выражение. Перегрузка оператора будет использовать ADL для поиска оператора [over.match.oper] /3.2:

Набор кандидатов, не являющихся членами, является результатом неквалифицированного поиска оператора @ в контексте выражения в соответствии с обычными правилами поиска имени в неквалифицированных вызовах функций (6.4.2) за исключением того, что все функции-члены игнорируются. Однако, если ни у одного операнда нет типа класса, только те, которые не являются членами
функции в наборе поиска, которые имеют первый параметр типа T1 или «ссылку на cv T1», когда T1 является типом перечисления, или (если есть правый операнд) второй параметр типа T2 или «ссылку на cv T2» , когда T2 является типом перечисления, являются функциями-кандидатами.

Но так как ваш operator+ является не в том же пространстве имен, что и любой аргумент, поиск ADL завершится неудачно. И список кандидатов, не являющихся членами, не будет автоматически включать глобальные функции, у него нет шансов найти подходящее operator+,

Так что вы не можете фактически перегрузить такой оператор, не открывая пространство имен. Что, конечно, запрещено для std,

2
По вопросам рекламы [email protected]