-
Notifications
You must be signed in to change notification settings - Fork 12
Open
Description
It looks like the user-provided tag_invoke overload creates ambiguity if the type also matches other categories of types supported by Boost.Hash2. For example:
#include <iostream>
#include <boost/describe.hpp>
#include <boost/hash2/fnv1a.hpp>
#include <boost/hash2/hash_append.hpp>
struct X
{
int a;
template< typename Hash, typename Flavor >
friend void tag_invoke(boost::hash2::hash_append_tag const&,
Hash& h, Flavor const& f, X const& v)
{
std::cout << "Called my tag_invoke" << std::endl;
boost::hash2::hash_append(h, f, v.a);
}
};
BOOST_DESCRIBE_STRUCT(X, (), (a))
int main()
{
boost::hash2::fnv1a_32 h1;
X v1 = { 1 };
boost::hash2::hash_append( h1, {}, v1 );
}
Gcc 13.2 output:
In file included from test_tag_invoke.cpp:4:
./include/boost/hash2/hash_append.hpp: In instantiation of ‘constexpr void boost::hash2::hash_append(Hash&, const Flavor&, const T&) [with Hash = fnv1a_32; Flavor = default_flavor; T = X]’:
test_tag_invoke.cpp:25:30: required from here
./include/boost/hash2/hash_append.hpp:419:31: error: call of overloaded ‘do_hash_append(boost::hash2::fnv1a_32&, const boost::hash2::default_flavor&, const X&)’ is ambiguous
419 | detail::do_hash_append( h, f, v );
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
./include/boost/hash2/hash_append.hpp:357:5: note: candidate: ‘constexpr typename std::enable_if<boost::container_hash::is_described_class<T>::value, void>::type boost::hash2::detail::do_hash_append(Hash&, const Flavor&, const T&) [with Hash = boost::hash2::fnv1a_32; Flavor = boost::hash2::default_flavor; T = X; typename std::enable_if<boost::container_hash::is_described_class<T>::value, void>::type = void]’
357 | do_hash_append( Hash& h, Flavor const& f, T const& v )
| ^~~~~~~~~~~~~~
./include/boost/hash2/hash_append.hpp:401:5: note: candidate: ‘constexpr typename std::enable_if<boost::hash2::detail::has_tag_invoke<T>::value, void>::type boost::hash2::detail::do_hash_append(Hash&, const Flavor&, const T&) [with Hash = boost::hash2::fnv1a_32; Flavor = boost::hash2::default_flavor; T = X; typename std::enable_if<has_tag_invoke<T>::value, void>::type = void]’
401 | do_hash_append( Hash& h, Flavor const& f, T const& v )
| ^~~~~~~~~~~~~~
I think, a user-provided tag_invoke
should always be preferred even if the type matches one of the natively supported type category. The code above is expected to compile and output "Called my tag_invoke".
Metadata
Metadata
Assignees
Labels
No labels