Можно ли вводить специализацию в пространство имен std?
В этой статье по определению собственных расширений до ::std::error_code
автор рекомендует этот код:
namespace std
{
template <>
struct is_error_code_enum<http_error>
: public true_type {};
}
чтобы включить преобразования из ваших собственных констант ошибок в системный тип ошибки.
Это разумно? Это всегда заставляет меня нервничать, чтобы помещать вещи в пространство имен std
. Есть ли лучший способ достижения цели? В противном случае, есть ли часть стандарта, в котором говорится, что это всегда нормально делать?
Ответы
Ответ 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. Возможно, это предпочтительнее.
Я, вероятно, вернусь и снова отредактирую после того, как проверил.