어떻게 해쉬와 비교 포인터 멤버-기능입니까?
-
19-09-2019 - |
문제
나는 어떻게 해시(std::tr1::hash 또는 부스트::hash)c++멤버 포인터-기능입니까?
예제:
나는 여러 bool(Class::*functionPointer)()(static)는 점을 여러 가지 다른 방법의 클래스 클래스고 해시 사람들 멤버 포인터 기능입니다.
렇게 하려면 어떻게 해야 합니까?
도 어떻게 비교할 수 있습니(std::less)그 멤버 함수 포인터 그래서 저장할 수 있는 그들을에서는 std::니까?
해결책
모든 C++개체를 포함하여 포인터가 멤버 함수는 표현으로 메모리에 배열의 명령입니다.그렇게 시도할 수 있습니다:
bool (Class::*fn_ptr)() = &Class::whatever;
const char *ptrptr = static_cast<const char*>(static_cast<const void*>(&fn_ptr));
지금 치료 ptrptr
으로 가리키는 배열의 (sizeof(bool (Class::*)()))
바이트를,그리고 해시 또는 그들을 비교 바이트입니다.당신이 사용할 수 있는 unsigned char
대 char
당신이 선호하는 경우.
이 보증은 없는 틀린 확실성에서는 C++03,포인터가 멤버 함수는 포드 의미는 다른 것들 사이에 그들은 복사할 수 있습 memcpy 를 사용하여.이것이 의미하는 경우 동일한 바이트 단위 값을,그리고 그들은 동일합니다.
문제는 저장을 표현의 멤버 함수 포인터를 포함할 수 있는 비트에 참여하지 않는 값 그래서 그들은 반드시 동일한 다른 포인터를 동원 기능입니다.또는 컴파일러가 있습,일부 모호한 이유가 있는 하나 이상의 방법을 가리키는 동일한 기능의 동일한 클래스는 바이트 같습니다.어느 쪽이든 얻을 수 있는 틀린 네거티브.당신이 볼 필요가 있는 방법으로 멤버 함수 포인터 실제 작업에서 당신의 구현합니다.그것을 구현해야 합니다 operator==
구성원에 대한 함수 포인터 어떻게든,당신이 할 수 있는 방법을 찾을 수 있습니다 다음은 아마 그 밖으로 주문 및 해쉬 기능입니다.
는 잠재적으로는 하드:멤버 함수 포인터가 어색하고,저장소를 포함할 가능성이 서로 다른 많은 양의 비 참여하는"여유 공간에 따라"어떤 종류의 기능은 지적(가상,상속).그래서 당신은 아마 상호 작용하는 매우와 크게 컴파일러의 구현세요.이 문서에서도 도움 당신이 시작하기: http://www.codeproject.com/KB/cpp/FastDelegate.aspx
깨끗한 대체 할 수 있습 선형 검색을 배열을 통해하기 위해서"canonicalise"모든 기능 포인터,다음을 비교하고 해시의 위치를 기반으로는"표준"의 인스턴스는 함수 포인터에서 당신의 배열입니다.따라 성능 요구사항니다.심지어 있는 경우,요구 사항은 클래스(및 그 파생된 클래스)가 이렇게 많은 기능을 하는 선형 검색을 하는?
typedef bool (Class::*func)();
vector<func> canon;
size_t getIndexOf(func fn_ptr) {
vector<func>::iterator it = find(canon.begin(), canon.end(), fn_ptr);
if (it != canon.end()) return it - canon.begin();
canon.push_back(func);
return canon.size() - 1;
}
다른 팁
이전 답변에 설명 된대로 포인터 (Microsoft Compiler 2010)를 캐스트 할 수 없었지만 이것은 나에게 효과적입니다.
static string fmptostr(int atype::*opt)
{
char buf[sizeof(opt)];
memcpy(&buf,&opt,sizeof(opt));
return string(buf,sizeof(opt));
}
포인터의 비트 타이어 아이덴티티에 대해서는 적절한 컴파일러 스위치를 사용하는 경우 비트가 될 수 있습니다. 적어도 이것은 #pragma pointers_to_members와 스위치를 사용하는 Microsoft 컴파일러 예를 들어 .../vmg을 사용합니다.
멤버 기능 포인터가 고유 한 경우 대부분의 경우 콜백 기반 구독의 경우에 사실입니다. type_index, 유형의 독창성으로 보장되는 독창성 Class::Method
) 프로그램에서 저장하기에 적합합니다. unordered_map
, 즉
struct MyEvent {
using fn_t = std::function<void(MyEvent &)>;
using map_t = std::unordered_map<std::type_index, fn_t>;
template <typename Handler>
void subscribe(Object& obj, Handler&& handler) {
fn_t fn = [&, handler = std::move(handler)](MyEvent& event) {
(obj.*handler)(event);
}
std::type_index index = typeid(Handler);
subscribers.emplace(std::move(index), std::move(fn));
}
void fire() {
for(auto& pair: subscribers) {
auto& fn = pair.second;
fn(*this);
}
}
map_t subscribers;
}
구독 및 화재 이벤트 예제 :
MyEvent event;
MyObject obj = ...;
event.subscribe(obj, &MyObject::on_event );
...
event.fire();
따라서 위의 예는 클래스/메소드 고유성을 제공하며 객체/방법 고유성이 필요한 경우 구조물이 있어야합니다. std::hash<MyObject>
그리고 이미 있습니다 std::hash<std::type_index>
멤버 기능 포인터의 경우.