문제

나는 어떻게 해시(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 charchar 당신이 선호하는 경우.

이 보증은 없는 틀린 확실성에서는 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> 멤버 기능 포인터의 경우.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top