Skip to content

Commit

Permalink
Update is_contiguously_hashable to take endianness; remove is_uniquel…
Browse files Browse the repository at this point in the history
…y_represented
  • Loading branch information
pdimov committed Dec 7, 2023
1 parent 63baf5b commit a31dab5
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 200 deletions.
4 changes: 2 additions & 2 deletions benchmark/keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ template<class H> class hasher3
H h( seed_ );

STATIC_ASSERT( boost::hash2::is_contiguous_range<T>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, H>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, boost::hash2::endian::native>::value );

typename T::value_type const * p = v.data();
typename T::size_type n = v.size();
Expand Down Expand Up @@ -240,7 +240,7 @@ template<class H> class hasher4
H h( h_ );

STATIC_ASSERT( boost::hash2::is_contiguous_range<T>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, H>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, boost::hash2::endian::native>::value );

typename T::value_type const * p = v.data();
typename T::size_type n = v.size();
Expand Down
4 changes: 2 additions & 2 deletions benchmark/unordered.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ template<class H> class hasher3
H h( seed_ );

STATIC_ASSERT( boost::hash2::is_contiguous_range<T>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, H>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, boost::hash2::endian::native>::value );

typename T::value_type const * p = v.data();
typename T::size_type n = v.size();
Expand Down Expand Up @@ -198,7 +198,7 @@ template<class H> class hasher4
H h( h_ );

STATIC_ASSERT( boost::hash2::is_contiguous_range<T>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, H>::value );
STATIC_ASSERT( boost::hash2::is_contiguously_hashable<typename T::value_type, boost::hash2::endian::native>::value );

typename T::value_type const * p = v.data();
typename T::size_type n = v.size();
Expand Down
6 changes: 3 additions & 3 deletions include/boost/hash2/hash_append.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef BOOST_HASH2_HASH_APPEND_HPP_INCLUDED
#define BOOST_HASH2_HASH_APPEND_HPP_INCLUDED

// Copyright 2017, 2018 Peter Dimov.
// Copyright 2017, 2018, 2023 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
//
Expand Down Expand Up @@ -59,7 +59,7 @@ template<class H> void hash_append_range_( H & h, unsigned char const * first, u

template<class H, class T>
typename std::enable_if<
is_contiguously_hashable<T, H>::value, void >::type
is_contiguously_hashable<T, endian::native>::value, void >::type
hash_append_range_( H & h, T * first, T * last )
{
unsigned char const * f2 = reinterpret_cast<unsigned char const*>( first );
Expand Down Expand Up @@ -118,7 +118,7 @@ template<class H, class It> void hash_append_sized_range( H & h, It first, It la

template<class H, class T>
typename std::enable_if<
is_contiguously_hashable<T, H>::value, void >::type
is_contiguously_hashable<T, endian::native>::value, void >::type
do_hash_append( H & h, T const & v )
{
unsigned char const * p = reinterpret_cast<unsigned char const*>( &v );
Expand Down
47 changes: 43 additions & 4 deletions include/boost/hash2/is_contiguously_hashable.hpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,57 @@
#ifndef BOOST_HASH2_IS_CONTIGUOUSLY_HASHABLE_HPP_INCLUDED
#define BOOST_HASH2_IS_CONTIGUOUSLY_HASHABLE_HPP_INCLUDED

// Copyright 2017 Peter Dimov.
// Copyright 2017, 2023 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/hash2/is_uniquely_represented.hpp>
#include <boost/hash2/endian.hpp>
#include <type_traits>
#include <cstddef>

namespace boost
{
namespace hash2
{

template<class T, class H> struct is_contiguously_hashable:
is_uniquely_represented<T>
namespace detail
{

// is_trivially_equality_comparable

template<class T> struct is_trivially_equality_comparable:
std::integral_constant< bool, std::is_integral<T>::value || std::is_enum<T>::value || std::is_pointer<T>::value >
{
};

template<class T> struct is_trivially_equality_comparable<T const>:
is_trivially_equality_comparable<T>
{
};

// is_endian_independent

template<class T> struct is_endian_independent:
std::integral_constant< bool, sizeof(T) == 1 >
{
};

template<class T> struct is_endian_independent<T const>:
is_endian_independent<T>
{
};

} // namespace detail

// is_contiguously_hashable

template<class T, endian E> struct is_contiguously_hashable:
std::integral_constant<bool, detail::is_trivially_equality_comparable<T>::value && (E == endian::native || detail::is_endian_independent<T>::value)>
{
};

template<class T, std::size_t N, endian E> struct is_contiguously_hashable<T[N], E>:
is_contiguously_hashable<T, E>
{
};

Expand Down
39 changes: 0 additions & 39 deletions include/boost/hash2/is_uniquely_represented.hpp

This file was deleted.

1 change: 0 additions & 1 deletion test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import testing ;

# type traits

run is_uniquely_represented.cpp ;
run is_contiguously_hashable.cpp ;
run is_range.cpp ;
run is_contiguous_range.cpp ;
Expand Down
188 changes: 131 additions & 57 deletions test/is_contiguously_hashable.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// Copyright 2017 Peter Dimov.
// Copyright 2017, 2023 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/hash2/is_contiguously_hashable.hpp>
#include <boost/hash2/endian.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <cstddef>

struct H
{
};

class X;

struct Y
Expand All @@ -21,76 +18,153 @@ enum E
v
};

template<class T> void test_true_()
template<class T, boost::hash2::endian N> void test( bool exp )
{
using boost::hash2::is_contiguously_hashable;

BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T, H>));
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T const, H>));
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T[2], H>));
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T const [2], H>));
if( exp )
{
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T, N>));
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T const, N>));
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T[2], N>));
BOOST_TEST_TRAIT_TRUE((is_contiguously_hashable<T const [2], N>));
}
else
{
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T, N>));
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T const, N>));
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T[2], N>));
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T const [2], N>));
}
}

template<class T> void test_false_()
int main()
{
using boost::hash2::is_contiguously_hashable;
using boost::hash2::endian;

BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T, H>));
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T const, H>));
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T[2], H>));
BOOST_TEST_TRAIT_FALSE((is_contiguously_hashable<T const [2], H>));
}
//

template<class T> void test_true()
{
test_true_<T>();
test_true_<T*>();
test_true_<T[2]>();
test_true_<T[2][2]>();
}
test<bool, endian::native>( true );

template<class T> void test_false()
{
test_false_<T>();
test_true_<T*>();
test_false_<T[2]>();
test_false_<T[2][2]>();
}
//

int main()
{
test_true_<bool>();
test<char, endian::native>( true );
test<char, endian::little>( true );
test<char, endian::big>( true );

test<signed char, endian::native>( true);
test<signed char, endian::little>( true );
test<signed char, endian::big>( true );

test<unsigned char, endian::native>( true );
test<unsigned char, endian::little>( true );
test<unsigned char, endian::big>( true );

test<wchar_t, endian::native>( true );
test<wchar_t, endian::little>( endian::native == endian::little );
test<wchar_t, endian::big>( endian::native == endian::big );

test<char16_t, endian::native>( true );
test<char16_t, endian::little>( endian::native == endian::little );
test<char16_t, endian::big>( endian::native == endian::big );

test<char32_t, endian::native>( true );
test<char32_t, endian::little>( endian::native == endian::little );
test<char32_t, endian::big>( endian::native == endian::big );

//

test<short, endian::native>( true );
test<short, endian::little>( endian::native == endian::little );
test<short, endian::big>( endian::native == endian::big );

test<unsigned short, endian::native>( true );
test<unsigned short, endian::little>( endian::native == endian::little );
test<unsigned short, endian::big>( endian::native == endian::big );

test<int, endian::native>( true );
test<int, endian::little>( endian::native == endian::little );
test<int, endian::big>( endian::native == endian::big );

test<unsigned int, endian::native>( true );
test<unsigned int, endian::little>( endian::native == endian::little );
test<unsigned int, endian::big>( endian::native == endian::big );

test<long, endian::native>( true );
test<long, endian::little>( endian::native == endian::little );
test<long, endian::big>( endian::native == endian::big );

test<unsigned long, endian::native>( true );
test<unsigned long, endian::little>( endian::native == endian::little );
test<unsigned long, endian::big>( endian::native == endian::big );

test<unsigned short, endian::native>( true );
test<unsigned short, endian::little>( endian::native == endian::little );
test<unsigned short, endian::big>( endian::native == endian::big );

//

test<float, endian::native>( false );
test<float, endian::little>( false );
test<float, endian::big>( false );

test<double, endian::native>( false );
test<double, endian::little>( false );
test<double, endian::big>( false );

test<long double, endian::native>( false );
test<long double, endian::little>( false );
test<long double, endian::big>( false );

//

test<std::nullptr_t, endian::native>( false );
test<std::nullptr_t, endian::little>( false );
test<std::nullptr_t, endian::big>( false );

test<void*, endian::native>( true );
test<void*, endian::little>( endian::native == endian::little );
test<void*, endian::big>( endian::native == endian::big );

test<void const*, endian::native>( true );
test<void const*, endian::little>( endian::native == endian::little );
test<void const*, endian::big>( endian::native == endian::big );

test<void(*)(), endian::native>( true );
test<void(*)(), endian::little>( endian::native == endian::little );
test<void(*)(), endian::big>( endian::native == endian::big );

//

test<E, endian::native>( true );
test<E, endian::little>( endian::native == endian::little || sizeof(E) == 1 );
test<E, endian::big>( endian::native == endian::big || sizeof(E) == 1 );

test_true_<char>();
test_true_<signed char>();
test_true_<unsigned char>();
test_true_<wchar_t>();
test_true_<char16_t>();
test_true_<char32_t>();
//

test_true_<short>();
test_true_<unsigned short>();
test_true_<int>();
test_true_<unsigned int>();
test_true_<long>();
test_true_<unsigned long>();
test_true_<unsigned short>();
test<X*, endian::native>( true );
test<X*, endian::little>( endian::native == endian::little );
test<X*, endian::big>( endian::native == endian::big );

test_false_<float>();
test_false_<double>();
test_false_<long double>();
//

test_false_<std::nullptr_t>();
test<Y, endian::native>( false );
test<Y, endian::little>( false );
test<Y, endian::big>( false );

test_true_<void*>();
test_true_<void const*>();
test<Y*, endian::native>( true );
test<Y*, endian::little>( endian::native == endian::little );
test<Y*, endian::big>( endian::native == endian::big );

test_true_<void(*)()>();
test<int Y::*, endian::native>( false );
test<int Y::*, endian::little>( false );
test<int Y::*, endian::big>( false );

test_true_<E>();
test<void (Y::*)(), endian::native>( false );
test<void (Y::*)(), endian::little>( false );
test<void (Y::*)(), endian::big>( false );

test_false_<X>();
test_false_<Y>();
//

return boost::report_errors();
}
Loading

0 comments on commit a31dab5

Please sign in to comment.