Подтвердить что ты не робот

Можно ли вводить специализацию в пространство имен std?

В этой статье по определению собственных расширений до ::std::error_code автор рекомендует этот код:

namespace std
{
  template <>
  struct is_error_code_enum<http_error>
    : public true_type {};
}

чтобы включить преобразования из ваших собственных констант ошибок в системный тип ошибки.

Это разумно? Это всегда заставляет меня нервничать, чтобы помещать вещи в пространство имен std. Есть ли лучший способ достижения цели? В противном случае, есть ли часть стандарта, в котором говорится, что это всегда нормально делать?

4b9b3361

Ответ 1

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

См. 17.6.4.2.1 в черновике С++ 0x.

Новые типы, перегрузки функций и все остальное, конечно, запрещено. Но специализации существующих шаблонов разрешены.

Ответ 2

Это не совсем нормально - в некоторых случаях это необходимо. То, что вы не должны делать, - это определить совершенно новые функции/классы/шаблоны в std.

std::swap, в частности, является общей и простой задачей специализации. Некоторым классам необходимо сделать это, чтобы обеспечить эффективные свопы, в основном заменяя частные ссылки на внутреннюю среду обмена, а не используя реализацию временных и временных заданий по умолчанию.

ИЗМЕНИТЬ

Комментарий ildjarn упоминает ADL - Аргумент Зависимое имя Поиск. Страница Wikipedia специально упоминает std::swap в разделе "Интерфейсы" и "Критика".

В разделе 13.5.2 от Stroustrup (Special Edition) приведен пример специализации std::swap. Цитата из этого...

Эти специализации less() и swap() используются в стандартной библиотеке (16.3.9, 20.3.16). Кроме того, они являются примерами широко применяемых методов.

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

Также возможно, что существует проблема стиля, которая не была решена после публикации специального издания. AFAIK, Stroustrup добавили некоторые дополнительные приложения и применили некоторые ошибки, но в противном случае существенно не изменили содержание.

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

Хорошо, да, ADL существует по какой-то причине - так что наряду с типом видны функции и операторы, не являющиеся членами, которые работают со временем. Но std::swap не связан с одним конкретным типом - он является общим, и только определенные специализации связаны с конкретными типами. Если вы хотите, чтобы std::swap был видимым, вы хотите использовать пространство имен std. ADL не является необходимым для выполнения этой работы, и, как указывает на странице Википедии, есть критические замечания по ADL.

Что это значит, в основном, я не знаю. У меня есть мои рационализации. Они не обязательно соглашаются с более распространенными правилами стиля. Конечно, этот комментарий доказывает, что для специализации std::swap не обязательно специализироваться - вы можете предоставить свой собственный отдельный swap и вместо этого полагаться на ADL. Возможно, это предпочтительнее.

Я, вероятно, вернусь и снова отредактирую после того, как проверил.