20

std::hash関数ポインターのハッシュにC++11 型を使用できますか? hash次のように定義された部分的な特殊化があります。

template <typename T> struct hash<T*>;

しかし、関数ポインターは C++ の他のポインター型とは異なるため (たとえば、 にキャストすることはできません)、やvoid*のような型に使用しても安全かどうかはわかりません。int(*)()void(*)(int, int)

これは許可されていますか?新しい ISO 仕様に、これを支持または反論する特定の文言はありますか?

ありがとう!

4

3 に答える 3

11

素晴らしい質問です。確かな答えはわかりませんが、私よりも知識のある人に喜んで委ねますが、関数ポインターはデータポインターと同じではありませんが、それでもポインターであると考えています。std::hash<T*>部分的な特殊化を適用する必要があります。

価値のあることとして、以下-pendanticは g++ 4.8.1 および clang 3.3 でも警告なしでコンパイルされ、期待どおりに動作します。

#include <functional>
#include <iostream>

void func1(int) {}
void func2(int) {}

int main()
{
    typedef void (*func_type) (int);

    std::hash<func_type> hash;

    std::cout << hash(func1) << std::endl;
    std::cout << hash(func2) << std::endl;

}

ただし、これを裏付けるために標準への参照があれば、本当に興味があります。

于 2013-11-01T03:14:50.817 に答える
-1

それは実際に興味深いです... MSVC ++を使用しているときにこの質問に出くわしました。私がやろうとしていることは次のとおりです。

static std::unordered_map<Fun, std::string> FunctionMap()
{
    static std::unordered_map<Fun, std::string> map;
    return map;
}

関数ポインター型の Fun を使用します。

コンパイル中に、次のエラーが発生します。

error C2338: The C++ Standard doesn't provide a hash for this type.
....
_Kty=int (__thiscall Testje::* )(int,int)

以前の試みで、関数ポインタを にキャストしようとしましたがvoid*、これは許可されておらず、コンパイルできません (参照: https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-詳細についてはto-voidptrを参照してください)。その理由は、void* はデータ ポインターであり、関数ポインターはコード ポインターだからです。

これまでの私の結論は、許可されておらず、MSVC++ でコンパイルできないということです。

于 2015-04-22T12:39:47.543 に答える