Skip to content

Commit 148edc8

Browse files
committed
Provide non standard extensions also with std::bit, unless explicitly omitted (#8, thanks @electricbrass)
1 parent a7de60a commit 148edc8

File tree

2 files changed

+118
-45
lines changed

2 files changed

+118
-45
lines changed

include/nonstd/bit.hpp

Lines changed: 112 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
# define bit_HAVE_BYTESWAP 0
8080
#endif
8181

82+
// Provide bit functions in namespace nonstd :
83+
8284
namespace nonstd
8385
{
8486
using std::bit_cast;
@@ -104,6 +106,85 @@ namespace nonstd
104106
using std::endian;
105107
}
106108

109+
//
110+
// Provide bit extensions (at bottom), unless omitted:
111+
//
112+
113+
#if ! bit_CONFIG_STRICT
114+
115+
// Additional includes needed for extensions:
116+
117+
#include <climits> // CHAR_BIT
118+
119+
// Macros needed for extensions:
120+
121+
#define bit_noexcept noexcept
122+
123+
#ifdef _MSC_VER
124+
# include <cstdlib>
125+
# define bit_byteswap16 _byteswap_ushort
126+
# define bit_byteswap32 _byteswap_ulong
127+
# define bit_byteswap64 _byteswap_uint64
128+
#else
129+
# define bit_byteswap16 __builtin_bswap16
130+
# define bit_byteswap32 __builtin_bswap32
131+
# define bit_byteswap64 __builtin_bswap64
132+
#endif
133+
134+
// Detail needed for extensions:
135+
136+
namespace nonstd {
137+
namespace bit {
138+
139+
// C++11 emulation:
140+
141+
namespace std11 {
142+
143+
using std::uint8_t;
144+
using std::uint16_t;
145+
using std::uint32_t;
146+
using std::uint64_t;
147+
148+
using std::integral_constant;
149+
using std::true_type;
150+
using std::false_type;
151+
152+
using std::is_trivial;
153+
using std::is_trivially_copyable;
154+
using std::is_copy_constructible;
155+
using std::is_move_constructible;
156+
using std::is_unsigned;
157+
using std::is_same;
158+
159+
} // namespace std11
160+
161+
// Detail appearing for extensions both with std::bit and nonstd::bit:
162+
163+
// make sure all unsigned types are covered, see
164+
// http://ithare.com/c-on-using-int_t-as-overload-and-template-parameters/
165+
166+
template< size_t N > struct uint_by_size;
167+
template<> struct uint_by_size< 8> { typedef std11::uint8_t type; };
168+
template<> struct uint_by_size<16> { typedef std11::uint16_t type; };
169+
template<> struct uint_by_size<32> { typedef std11::uint32_t type; };
170+
#if bit_CPP11_OR_GREATER
171+
template<> struct uint_by_size<64> { typedef std11::uint64_t type; };
172+
#endif
173+
174+
template< typename T >
175+
struct normalized_uint_type
176+
{
177+
typedef typename uint_by_size< CHAR_BIT * sizeof( T ) >::type type;
178+
179+
static_assert( std::is_integral<T>::value, "integral type required.");
180+
static_assert( std11::is_unsigned<type>::value, "unsigned type result expected.");
181+
static_assert( sizeof( type ) == sizeof( T ), "size of determined type differs from type derived from.");
182+
};
183+
184+
}} // namespace nonstd::bit
185+
186+
#endif // bit_CONFIG_STRICT
187+
107188
#else // bit_USES_STD_BIT
108189

109190
// half-open range [lo..hi):
@@ -788,7 +869,36 @@ class endian
788869
} // namespace nonstd
789870

790871
//
791-
// Extensions: endian conversions
872+
// Make type available in namespace nonstd:
873+
//
874+
875+
namespace nonstd
876+
{
877+
using bit::bit_cast;
878+
879+
using bit::has_single_bit;
880+
using bit::bit_ceil;
881+
using bit::bit_floor;
882+
using bit::bit_width;
883+
884+
using bit::rotl;
885+
using bit::rotr;
886+
887+
using bit::countl_zero;
888+
using bit::countl_one;
889+
using bit::countr_zero;
890+
using bit::countr_one;
891+
using bit::popcount;
892+
893+
using bit::byteswap;
894+
895+
using bit::endian;
896+
}
897+
898+
#endif // bit_USES_STD_BIT
899+
900+
//
901+
// Extensions (unless omitted): endian conversions
792902
//
793903

794904
#if !bit_CONFIG_STRICT
@@ -949,32 +1059,9 @@ inline T as_native_endian( T v ) bit_noexcept
9491059
#endif // !bit_CONFIG_STRICT
9501060

9511061
//
952-
// Make type available in namespace nonstd:
1062+
// Make extensions available in namespace nonstd:
9531063
//
9541064

955-
namespace nonstd
956-
{
957-
using bit::bit_cast;
958-
959-
using bit::has_single_bit;
960-
using bit::bit_ceil;
961-
using bit::bit_floor;
962-
using bit::bit_width;
963-
964-
using bit::rotl;
965-
using bit::rotr;
966-
967-
using bit::countl_zero;
968-
using bit::countl_one;
969-
using bit::countr_zero;
970-
using bit::countr_one;
971-
using bit::popcount;
972-
973-
using bit::byteswap;
974-
975-
using bit::endian;
976-
}
977-
9781065
#if !bit_CONFIG_STRICT
9791066

9801067
namespace nonstd
@@ -994,6 +1081,4 @@ namespace nonstd
9941081

9951082
#endif // !bit_CONFIG_STRICT
9961083

997-
#endif // bit_USES_STD_BIT
998-
9991084
#endif // NONSTD_BIT_LITE_HPP

test/bit.t.cpp

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,7 @@ CASE( "endian: little differs from big (corner-case when all scalars have size o
338338

339339
CASE( "to_big_endian(): convert native, or little or big endian specified unsigned to big endian" " [bit.endian.extension]" )
340340
{
341-
#if bit_USES_STD_BIT
342-
EXPECT( !!"Extension to_big_endian() not available (bit_USES_STD_BIT)" );
343-
#elif bit_CONFIG_STRICT
341+
#if bit_CONFIG_STRICT
344342
EXPECT( !!"Extension to_big_endian() not available (bit_CONFIG_STRICT)" );
345343
#else
346344
EXPECT( to_big_endian( uint8_t(0x5eu) ) == 0x5eu );
@@ -359,9 +357,7 @@ CASE( "to_big_endian(): convert native, or little or big endian specified unsign
359357

360358
CASE( "to_little_endian(): convert native, or little or big endian specified unsigned to little endian" " [bit.endian.extension]" )
361359
{
362-
#if bit_USES_STD_BIT
363-
EXPECT( !!"Extension to_little_endian() not available (bit_USES_STD_BIT)" );
364-
#elif bit_CONFIG_STRICT
360+
#if bit_CONFIG_STRICT
365361
EXPECT( !!"Extension to_little_endian() not available (bit_CONFIG_STRICT)" );
366362
#else
367363
EXPECT( to_little_endian( uint8_t(0x5eu) ) == 0x5eu );
@@ -380,9 +376,7 @@ CASE( "to_little_endian(): convert native, or little or big endian specified uns
380376

381377
CASE( "to_native_endian(): convert native, or little or big endian specified unsigned to native endian" " [bit.endian.extension]" )
382378
{
383-
#if bit_USES_STD_BIT
384-
EXPECT( !!"Extension to_native_endian() not available (bit_USES_STD_BIT)" );
385-
#elif bit_CONFIG_STRICT
379+
#if bit_CONFIG_STRICT
386380
EXPECT( !!"Extension to_native_endian() not available (bit_CONFIG_STRICT)" );
387381
#else
388382
EXPECT( to_native_endian( uint8_t(0x5eu) ) == 0x5eu );
@@ -419,9 +413,7 @@ CASE( "to_native_endian(): convert native, or little or big endian specified uns
419413

420414
CASE( "as_big_endian(): provide native unsigned as big endian" " [bit.endian.extension]" )
421415
{
422-
#if bit_USES_STD_BIT
423-
EXPECT( !!"Extension as_big_endian() not available (bit_USES_STD_BIT)" );
424-
#elif bit_CONFIG_STRICT
416+
#if bit_CONFIG_STRICT
425417
EXPECT( !!"Extension as_big_endian() not available (bit_CONFIG_STRICT)" );
426418
#else
427419
if ( endian::native == endian::big )
@@ -445,9 +437,7 @@ CASE( "as_big_endian(): provide native unsigned as big endian" " [bit.endian.ext
445437

446438
CASE( "as_little_endian(): provide native unsigned as little endian" " [bit.endian.extension]" )
447439
{
448-
#if bit_USES_STD_BIT
449-
EXPECT( !!"Extension as_little_endian() not available (bit_USES_STD_BIT)" );
450-
#elif bit_CONFIG_STRICT
440+
#if bit_CONFIG_STRICT
451441
EXPECT( !!"Extension as_little_endian() not available (bit_CONFIG_STRICT)" );
452442
#else
453443
if ( endian::native == endian::big )
@@ -471,9 +461,7 @@ CASE( "as_little_endian(): provide native unsigned as little endian" " [bit.endi
471461

472462
CASE( "as_native_endian(): provide native unsigned as native endian (identity)" " [bit.endian.extension]" )
473463
{
474-
#if bit_USES_STD_BIT
475-
EXPECT( !!"Extension as_native_endian() not available (bit_USES_STD_BIT)" );
476-
#elif bit_CONFIG_STRICT
464+
#if bit_CONFIG_STRICT
477465
EXPECT( !!"Extension as_native_endian() not available (bit_CONFIG_STRICT)" );
478466
#else
479467
EXPECT( as_native_endian( uint8_t (0x5eu ) ) == 0x5eu );

0 commit comments

Comments
 (0)