Norma mówi, że po około specjalizujący szablony z biblioteki standardowej (przez What can and can't I specialize in the std namespace?)Czy legalne jest wyspecjalizowanie funkcji biblioteki standardowej dla shared_ptr typu zdefiniowanego przez użytkownika?
Program może dodać szablon specjalizacji dla każdego Standard Template Library do namespace std tylko jeżeli zgłoszenie zależy od czytelnymi zdefiniowany typ i specjalizacja spełnia standardowe wymagania biblioteki dla oryginalnego szablonu i nie jest wyraźnie zabroniona.
Czy specjalizacja standardowych szablonów biblioteki ze standardową klasą bibliotek specjalizującą się w klasie zdefiniowanej przez użytkownika jest legalna?
Na przykład specjalizujący się w std::hash
dla std::shared_ptr<MyType>
?
Po przeczytaniu powyższego akapitu i połączonego pytania wygląda na to, że powinno być, ponieważ deklaracja specjalizacji jest zależna od MyType
, jednak "chyba że wyraźnie zabronione" niepokoi mnie nieco.
Poniższy przykład kompiluje i działa zgodnie z oczekiwaniami (AppleClang 7.3), ale czy jest legalny?
#include <unordered_set>
#include <memory>
#include <cassert>
#include <string>
struct MyType {
MyType(std::string id) : id(id) {}
std::string id;
};
namespace std {
template<>
struct hash<shared_ptr<MyType>> {
size_t operator()(shared_ptr<MyType> const& mine) const {
return hash<string>()(mine->id);
}
};
template<>
struct equal_to<shared_ptr<MyType>> {
bool operator()(shared_ptr<MyType> const& lhs, shared_ptr<MyType> const& rhs) const {
return lhs->id == rhs->id;
}
};
}
int main() {
std::unordered_set<std::shared_ptr<MyType>> mySet;
auto resultA = mySet.emplace(std::make_shared<MyType>("A"));
auto resultB = mySet.emplace(std::make_shared<MyType>("B"));
auto resultA2 = mySet.emplace(std::make_shared<MyType>("A"));
assert(resultA.second);
assert(resultB.second);
assert(!resultA2.second);
}
Tak, jest to zgodne z prawem, nie ma ograniczeń dotyczących specjalizacji 'std :: hash' z wyjątkiem * DefaultConstructible, CopyAssignable, Swappable i Destructible * (i wszystkich innych wymagań, które nie mają nic wspólnego z *" jawnie zabronione "*) . Jednym z przykładów specjalizacji * "wyraźnie zabronione" * jest specjalizacja 'std :: numeric_limits' dla niearytmetycznych standardowych typów. – Holt
Powinieneś rzucić okiem na odnośnik Argument Dependend, nie musisz dodawać funkcji do przestrzeni nazw standardu. –