26 #ifndef LSST_UTILS_TESTS_H 
   27 #define LSST_UTILS_TESTS_H 
   32 #include <type_traits> 
   40 template <
typename, 
typename = 
void>
 
   41 constexpr 
bool HAS_STREAM_OUTPUT = 
false;
 
   43 constexpr 
bool HAS_STREAM_OUTPUT<
 
   44         T, std::enable_if_t<true, decltype((void)(std::declval<std::ostream&>() << std::declval<T&>()),
 
   48 template <
typename T, 
class Hash>
 
   49 std::enable_if_t<HAS_STREAM_OUTPUT<T>> printIfHashEqual(T obj1, T obj2, Hash hash) {
 
   50     BOOST_TEST_REQUIRE(obj1 == obj2);
 
   51     BOOST_TEST(hash(obj1) == hash(obj2),
 
   52                obj1 << 
" == " << obj2 << 
", but " << hash(obj1) << 
" != " << hash(obj2));
 
   54 template <
typename T, 
class Hash>
 
   55 std::enable_if_t<!HAS_STREAM_OUTPUT<T>> printIfHashEqual(T obj1, T obj2, Hash hash) {
 
   56     if (!(obj1 == obj2)) {
 
   57         BOOST_FAIL(
"Unequal objects need not have equal hashes.");
 
   59     BOOST_TEST(hash(obj1) == hash(obj2));
 
   77                   "std::hash specializations must be default-constructible");
 
   82     static_assert(
is_same<
typename Hash::argument_type, remove_cv_t<T>>::value,
 
   83                   "std::hash must have an argument_type member until C++20");
 
   85                   "std::hash must have a result_type member until C++20");
 
   87     static_assert(
is_same<result_of_t<Hash(T)>, 
size_t>::value,
 
   88                   "std::hash specializations must be callable and return a size_t");
 
  101 template <
typename T>
 
  105     printIfHashEqual(obj1, obj2, Hash());