For boost container hash, I needed to provide an ADL-reachable hash_value
. I wanted to disable implicit conversions, so I wrote it as a template that forced the parameter to be the class type.
inline auto hash_value(std::same_as<ClassType> const auto& key) -> std::size_t;
To my surprise, it failed, but worked if I swapped the order of const
and auto
.
In order to build up a deeper understanding: How can I conceptually interpret this situation? The parameter has a placeholder type const auto&
and is given a specifier that denotes a constraint, I thought until now. But this rather appears to be a case where the sequence constraint auto
is a grammar that's specially detected and the mechanism fails if I reorder the type specifiers.
mechanism fails if I reorder the type specifiers
Correct. Because the constraint is not a type specifier on its own. Grammatically, it's part of the placeholder type itself
placeholder-type-specifier: type-constraintopt auto type-constraintopt decltype ( auto )
There is no room there for other specifiers. Conversely, this does work:
inline auto hash_value(const std::same_as<ClassType> auto& key) -> std::size_t;
If you are in the wrong left const camp, and not the right camp.