C++0x, пользовательские литералы с оператором друга ""()
Будет ли возможно и / или полезно определить operator "" (...)
как функция друга?
class Puzzle {
friend Puzzle operator "" _puzzle(const char*, size_t);
...
};
void solve(Puzzle);
int main() {
solve("oxo,xox"_puzzle);
};
Я думаю о "полезном" особенно из-за правила, которое operator ""
должны быть определены только в пространстве имен - не в последнюю очередь потому, что идентификаторы начинаются с _
зарезервированы в глобальном пространстве имен. Это friend
нарушая это правило здесь? Так что, с этой не совсем инкапсуляцией не было бы никакой пользы, верно?
3 ответа
Стандарт рассматривает это непосредственно в единственном месте, где упоминаются любые ограничения на объявления пользовательских литералов, §13.5.8/2:
Объявление, идентификатор объявления которого является литеральным идентификатором оператора, должно быть объявлением функции области имен пространства или шаблона функции (это может быть функция друга (11.3)), явной реализацией или специализацией шаблона функции или декларация использования (7.3.3).
Если друг также объявлен в области пространства имен, то нет никакого различия между определением в классе или области пространства имен. Обратите внимание, что нет никаких требований к определению в области имен, о чем говорит ваш вопрос в настоящее время.
Если он не объявлен в области имен, поскольку ADL не может найти его, друга можно использовать в частном порядке внутри класса, где он является областью при обычном поиске безоговорочного имени. Это единственный способ объявить буквальный оператор, который не является внешним интерфейсом.
Если друг определен внутри шаблона класса, то два экземпляра шаблона сгенерируют две функции с одинаковыми именами в области имен, которые конфликтуют, даже если обе они невидимы вне области класса.
В случае, если это помогает с синтаксисом, вот как я объявляю дружественный пользовательский литеральный оператор в классе, где сам оператор находится в пространстве имен:
class Integer;
namespace literals {
Integer operator "" _I (const char *);
}
// Infinite precision integer
class Integer {
public:
// Basic constructor & destructor
Integer ();
~Integer ();
... rest of the interface ...
// Literal operator
friend Integer literals::operator "" _I (const char *);
private:
struct Detail;
std::unique_ptr<Detail> detail;
};
Пользователи тянут в оператор с using namespace literals;
Заявление только если они этого хотят. (И, на самом деле, все это находится в родительском пространстве имен, но вы поняли идею).
Согласно стандарту, да, декларация о дружбе должна быть законной. Кстати, имя подходит для пользовательского кода, так как оно начинается с подчеркивания даже в глобальном пространстве имен.
Объявление друга позволит оператору получить доступ к частным данным класса.
Я начинаю сомневаться в полезности дружеских буквальных операторов. Поскольку пользовательские операторы могут иметь только несколько списков аргументов, невозможно указать класс в аргументах. Таким образом, теперь есть способ для зависимого от аргумента поиска найти правильную функцию. Я прав?