C ++ 0x, пользовательские литералы с оператором друга "" () - PullRequest
5 голосов
/ 09 сентября 2011

Будет ли возможно и / или полезно определить operator "" (...) как функцию друга?

class Puzzle {
  friend Puzzle operator "" _puzzle(const char*, size_t);
  ...
};
void solve(Puzzle);
int main() {
  solve("oxo,xox"_puzzle);
};

Я думаю о "полезности" особенно из-за правилачто operator "" должно быть определено только в пространстве имен - не в последнюю очередь потому, что идентификаторы, начинающиеся с _, зарезервированы в глобальном пространстве имен.Это friend нарушает это правило здесь?Так что, это инкапсуляция не принесет никакой пользы, верно?

Ответы [ 3 ]

2 голосов
/ 11 сентября 2011

Стандарт обращается к этому непосредственно в единственном месте, где он упоминает любые ограничения на объявления пользовательских литералов, §13.5.8 / 2:

Объявление, идентификатор объявления которого является литеральным идентификатором оператора, должно быть объявлением функции области имен пространства или шаблона функции ( это может быть функция друга (11.3) ), явная реализация или специализация шаблона функции, или объявление об использовании (7.3.3).

Если друг также объявлен в области пространства имен, то нет различия между определением в классе или области имен. Обратите внимание, что для определения пространства имен не требуется, что ваш вопрос, как формулирует ваш вопрос в настоящее время.

Если он не объявлен в области имен, поскольку ADL не может найти его, друга можно использовать в частном порядке внутри класса, где он является областью при обычном поиске безоговорочного имени. Это единственный способ объявления литерального оператора, который не является внешним интерфейсом.

Если друг определен в шаблоне класса, то два экземпляра шаблона сгенерируют две функции с одинаковыми именами в области имен, которые конфликтуют, даже если обе они невидимы вне области класса.

1 голос
/ 05 декабря 2011

В случае, если это помогает с синтаксисом, вот как я объявляю пользовательский литеральный оператор друга в классе, где сам оператор находится в пространстве имен:

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; заявление, только если они этого хотят.(И, на самом деле, все это находится в родительском пространстве имен, но вы поняли).

0 голосов
/ 09 сентября 2011

Согласно стандарту, да, декларация о дружбе должна быть законной.Кстати, имя подходит для пользовательского кода, поскольку оно начинается с подчеркивания даже в глобальном пространстве имен.

Объявление друга позволит оператору получить доступ к частным данным класса.

ЯНачинаем сомневаться в полезности знакомых буквальных операторов.Поскольку пользовательские операторы могут иметь только несколько списков аргументов, невозможно указать класс в аргументах.Таким образом, теперь есть способ для зависимого от аргумента поиска найти правильную функцию.Я прав?

...