/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: auHashUtils.hpp Date: 2022-3-23 Author: Reece ***/ #pragma once #include "auFNV1Utils.hpp" #define _AU_HASH_UTILS_HAS_STD // Thy shall pollute me, not std:: or any other namespace // ...namespace // ...namespace // Has the penny dropped yet? // It's amazing how every other language with a similar concept has conventions or other limitations on overloading packages/namespaces/modules, but C++ morons took the stance of the FSB on Chechnya, Crimea and Ukraine. // We could potentially be even nicer with a dedicated namespace (`AuUserHashes`?) for user-defined overloads and substitution-is-often-compiler-crash behavior on a nicer template (Static? ::Hashcode() instead of operator?), so that AuHash doesn't get invaded. template struct AuHasHashCode { template static constexpr AuTrueType Test(decltype(&C::HashCode)); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template constexpr inline bool AuHasHashCode_v = AuHasHashCode::type::value; namespace AuHash { template struct hash { #if defined(_AU_HASH_UTILS_HAS_STD) AuConditional_t, AuUInt8, std::hash> trashHasher; #endif AuUInt operator()(const Key &ref) const { if constexpr (AuHasHashCode_v) { return ref.HashCode(); } #if defined(_AU_HASH_UTILS_HAS_STD) else { return trashHasher(ref); } #endif } }; #define _HASH_F_CPP(type) \ template<> struct hash \ { \ AuUInt operator ()(type b) const \ { \ return AuFnv1aType(b); \ } \ }; _HASH_F_CPP(bool); _HASH_F_CPP(char); _HASH_F_CPP(signed char); _HASH_F_CPP(unsigned char); _HASH_F_CPP(char8_t); _HASH_F_CPP(char16_t); _HASH_F_CPP(char32_t); _HASH_F_CPP(wchar_t); _HASH_F_CPP(short); _HASH_F_CPP(unsigned short); _HASH_F_CPP(int); _HASH_F_CPP(unsigned int); _HASH_F_CPP(long); _HASH_F_CPP(long long); _HASH_F_CPP(unsigned long); _HASH_F_CPP(unsigned long long); _HASH_F_CPP(float); _HASH_F_CPP(double); _HASH_F_CPP(long double); _HASH_F_CPP(std::nullptr_t); #undef _HASH_F_CPP template struct hash { AuUInt operator ()(T *ptr) const { return AuUInt(ptr); } }; template struct less { constexpr bool operator()(const T &lhs, const T &rhs) const { if constexpr (AuHasHashCode_v) { return lhs.HashCode() < rhs.HashCode(); } else { return lhs < rhs; } } }; template struct equal { constexpr bool operator()(const T &lhs, const T &rhs) const { return lhs == rhs; } }; } template)> inline AuUInt AuHashCode(const T &ref) { return ref.HashCode(); } template)> inline AuUInt AuHashCode(const T &ref) { return AuHash::hash()(ref); } template struct AuEnableHashCodeOnData { AuUInt HashCode() const { return AuFnv1aType(*AuStaticCast(this)); } };