3

I have a templated class Foo that can do identity comparisons (via ==), but has a function Foo::sameStructureAs(Foo const & other) for more of a "value" vs. "pointer" notion of equality.

I'd like to make an unordered_map which overrides the hash function and the equality predicate. They default to std::equal_to<Key> and std::hash<Key>...which I provide for my type, based on identity. But I need them to be comparing on the basis of my sameStructureAs.

Since Foo is a template, I do something like this:

template <class> struct same_structure_as;

template <class> struct hash_structure;

template <class T>
struct hash_structure<Foo<T>>
{
    size_t operator() (Foo<T> const & value) const
    {
        // whatever...
    }
};

template <class T>
struct same_structure_as<Foo<T>>
{
    bool operator() (Foo<T> const & left, Foo<T> const & right) const
    {
        // whatever...
    }
};

Which seems like I'm following roughly the strategy of the classes in std:: for this purpose, and creating something general. So does that look right?

Secondly: Is there any precedent for the naming of this or a prototype already existing in std::? I've thought about words like isomorphic or congruent. It seems like something that would come up often in designing classes when you have more than one idea of what it means to be "equal".

1 Answers1

0

If you are looking at a type through this "different" notion of comparison or equality, ask if what you really need is another type. Perhaps there is some kind of cast or coercion you would apply to the underlying data so that its new notion of equality/assignment/comparison fits this test you are designing.

That way you can properly implement the std:: functions for that type... and use it in collections without having to pass in these extra predicates. So perhaps call the type with pointer-equality semantics FooRef and the one with value semantics Foo.

If for some reason you can't do this...then looking at the names one wants to parallel:

  • std::equal_to<Key>

  • std::hash<Key>

Keeping the equal_to and hash in there is probably the closest to "standard" one will accomplish. So rather than introducing new terms like congruence or isometric,call out exactly what is equal or getting hashed...and use the above as suffixes:

  • std::content_equal_to<Key>

  • std::content_hash<Key>

If it's the "structure" of something being compared you can apply that with structure_equal_to and structure_hash. Only caveat being that "struct"/"structure" has meaning in C++, so it may lead a reader to think it's comparing type_info or something like that.