简体   繁体   中英

Static std::hash function objects

C++ reference shows an example how to define custom hash function objects. In this example temporary hash<string> objects are created every time the call operator is executed:

namespace std
{
    template<> struct hash<S>
    {
        std::size_t operator()(S const& s) const noexcept
        {
            std::size_t h1 = std::hash<std::string>{}(s.first_name);
            std::size_t h2 = std::hash<std::string>{}(s.last_name);
            return h1 ^ (h2 << 1); // or use boost::hash_combine
        }
    };
}

I thought, would it be reasonable to make them static as they don't depend on any constructor arguments (default-constructible) and, basically, are just copies of each other?

namespace std
{
    template<> struct hash<S>
    {
        std::size_t operator()(S const& s) const noexcept
        {
            static std::hash<std::string> h;
            std::size_t h1 = h(s.first_name);
            std::size_t h2 = h(s.last_name);
            return h1 ^ (h2 << 1); // or use boost::hash_combine
        }
    };
}

Are there any disadvantages of this approach?

What do you think is involved with creating these function objects? You are allocating them on the stack, not on the heap. They don't have any members, so their size is zero. I guess a compiler might reserve a word for each of them on the stack, in order to give each one a unique this pointer... but that doesn't require any additional time, and I'd also expect the compiler to optimize this away since the class doesn't have any members and doesn't do anything with this .

In other words, the compiler will probably figure out that std::hash<std::string>{}(s.first_name) is just a function call and compile it as such.

I tried both methods and Clang 11.0.1 with -O3 at least generates the exact same code in both cases .

In C++ static variables in inline function should be shared between all copies of that function.Unused variables can be removed.

So far not a problem for an executable, but is much harder to achieve in dynamic libraries as user code might use another compiler and/or different optimizations and thus might generate an actual reference to that object even if it unused in the library itself.

I would expect some compilers on some platform to reserve 1 additional byte in data section and generate redundant export entry for such variable.

PS: Example of ICC generating additional symbol (remove static to see the difference).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM