Specializing types from namespace std based on user-defined concepts

120

Question: Specializing types from namespace std based on user-defined concepts

It is written in many places (for example here), that specialisations of types from namespace std are only allowed if the specialisation "depends on user-defined types". Does this definition in the standard explicitly exclude to specialise std types based on user-defined concepts?

For example, is this allowed?

namespace std {   template<MyConcept T>   struct hash<T> {     size_t hash(T const& v) const { ... }   }; } 

This would greatly simplify many specialisations in my code where I have a lot of different c++ error but similar classes adhering to the same concept which can be hashed all in the same way.

Total Answers: 1

90

Answers 1: of Specializing types from namespace std based on user-defined concepts

The general rule we have, in [namespace.std]/2 is:

Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std c++ error provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.

For this specialization:

template<MyConcept T> struct hash<T> { /* ... */ }; 

If it is the case that (a) for all T that satisfy MyConcept, T depends on at least one program-defined type and (b) this specialization meets the requirements for hash (i.e. it's invocable, swappable, satisfies the normal hash requirements, etc.), then this is fine.

By depends on at least one program-defined type, it's not just that it's like my::Type, but it could also include std::vector<my::Type> and std::tuple<int, char, my::Type*>, etc. As long as something in there somewhere is program-defined.