2
해시 할 수있는 클래스가 추상 기본 클래스 Hashable
입니다. 이제 std::hash
을 Hashable
에서 파생 된 모든 클래스로 확장하려고합니다.파생 클래스에 대한 표준화 표준 :: 해시
다음 코드는 정확히 수행해야합니다.
#include <functional>
#include <type_traits>
#include <iostream>
class Hashable {
public:
virtual ~Hashable() {}
virtual std::size_t Hash() const =0;
};
class Derived : public Hashable {
public:
std::size_t Hash() const {
return 0;
}
};
// Specialization of std::hash to operate on Hashable or any class derived from
// Hashable.
namespace std {
template<class C>
struct hash {
typename std::enable_if<std::is_base_of<Hashable, C>::value, std::size_t>::type
operator()(const C& object) const {
return object.Hash();
}
};
}
int main(int, char**) {
std::hash<Derived> hasher;
Derived d;
std::cout << hasher(d) << std::endl;
return 0;
}
GCC 4.8.1 예상대로 위의 코드는 정확히 작동하지만, 내가 GCC 4.7.2로 컴파일 할 때, 나는 다음과 같은 얻을 :
$ g++ -std=c++11 -o test test_hash.cpp
test_hash.cpp:22:8: error: redefinition of ‘struct std::hash<_Tp>’
In file included from /usr/include/c++/4.7/functional:59:0,
from test_hash.cpp:1:
/usr/include/c++/4.7/bits/functional_hash.h:58:12: error: previous definition of ‘struct std::hash<_Tp>’
/usr/include/c++/4.7/bits/functional_hash.h: In instantiation of ‘struct std::hash<Derived>’:
test_hash.cpp:31:24: required from here
/usr/include/c++/4.7/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
는 사람이 생각할 수 std::hash
의 전문화는 Hashable
에서 gcc 4.7.2로 파생 된 모든 클래스에서 작동합니까?
어를 더 그 코드가 손상되었습니다. 'std'에 새로운 템플릿을 선언 할 권한이 없습니다. 기존 템플릿의 전문화는 특정 조건에서만 작성할 수 있습니다. 당신이 가지고있는 것은 전문화가 아닙니다 –
표준 네임 스페이스에서 여러분이 할 수 있고 허용되지 않은 규칙을 무시하더라도 클래스는 어떤 컨텍스트에서도 허용되지 않는 재정의입니다. 두 정의가 일치하기 때문에 모호합니다. 당신은 각 타입을 위해 또는'Hashable'을 위해서만 전문화해야하고 그것의 파생 된 타입 모두를 위해'std :: hash'을 사용하면됩니다. 이것이 내가 adl을 통해 함수가 아니라 템플릿과 같은 형질을 싫어하는 이유입니다. –
John5342
의견을 보내 주셔서 감사합니다. 나는 나의 해결책이 상당히 정결하지 못하다는 것을 의심했고 실제로 gcc 4.8.1에서 전혀 효과가 없다는 것에 놀랐다. 각 파생 된 클래스에 대해 별도의 전문화를 작성하기로 결정했습니다. – Flecto