Is it OK to inject a specialization into the std namespace?
In this article on defining your own extensions to ::std::error_code
the author recommends this code:
namespace std
{
template <>
struct is_error_code_enum<http_error>
: public true_type {};
}
in order to enable conversions from your own error constants to the system error type.
Is this reasonable? It always makes me nervous to put things into the std
namespace. Is there a better way of accomplishing the goal? Failing all that, is there a part of the stand开发者_JAVA百科ard that says this is always OK to do?
Yep, specializations (for user-defined types) of existing std types are the only thing you're allowed to put in the std
namespace, as long as the specialization meets the requirements for the original template.
See 17.6.4.2.1 in the C++0x draft.
New types, function overloads and anything else, of course, is forbidden. But specializations of existing templates is allowed.
This isn't just OK - it's essential in some cases. What you shouldn't do is to define entirely new functions/classes/templates within std.
std::swap
in particular is a common and simple thing to specialise. Some classes need to do this to allow efficient swaps, basically swapping private references to exchange internals rather than using the default temporary-and-assignments implementation.
EDIT
The comment by ildjarn mentions ADL - Argument Dependent name Lookup. The Wikipedia page specifically mentions std::swap
in the "Interfaces" and "Criticism" section.
Section 13.5.2 of Stroustrup (Special Edition) includes an example of specialization of std::swap
. Quoting from that...
These specializations of
less()
andswap()
are used in the standard library (16.3.9, 20.3.16). In addition, they are examples of widely applicable techniques.
I've always read that as indicating that specialization of std::swap
was the right thing to do, and I've never worried enough about ADL to question that, but it's possible there's a gap between "used in the standard library" and "widely applicable techniques" - that this technique shouldn't be used to specialise std::swap
to handle types that aren't in std
.
It's also possible that there is a style issue that hadn't been decided back when the special edition was first published. AFAIK, Stroustrup has added some extra appendices and applied some errata, but otherwise not substantially revised the content.
Based on the Wikipedia page, there is a potential problem with mixing the addition of specialisations and ADL - sometimes you can get ambiguity preventing any lookup. This only happens if you mix the two techniques, and ADL is know for leading to semantic issues anyway. But that argument only leads to "don't use ADL at all", but ADL does exist for a reason.
Well, yes, ADL exists for a reason - so that non-member functions and operators that work with a time are visible along with the type. But std::swap
isn't associated with one particular type - it's generic, with only particular specializations being associated with particular types. If you want std::swap
to be visible, you want the std
namespace. ADL isn't necessary to make that work and, as the Wikipedia page points out, there are criticisms of ADL.
What this means is, basically, that I don't know. I have my rationalisations. They don't necessarily agree with more widespread style rules. Certainly this comment proves that it's not essential to specialise std::swap
- you can supply your own separate swap
and rely on ADL instead. Maybe that's preferred.
I'll probably come back and edit again after I've checked.
精彩评论