Revert to again supply the reverse_endianness_in_place template. This has the effect of providing a default reverse_endianness_in_place for user-defined types. Add error checking for UDT's to verify this works as desired. Provide a note in the conversion docs to that effect.

This commit is contained in:
Beman
2014-12-09 11:36:42 -05:00
parent a0b5805b73
commit 55a65c3806
3 changed files with 106 additions and 66 deletions

View File

@@ -164,8 +164,8 @@ instantiating a template.</p>
<code>x</code> is a value of a possibly <code>const</code> type convertible
to <code>Reversible</code>.</td>
<td>
<p>The value of <code>x</code> with the
order of its constituent bytes reversed is returned.</td>
<p>Returns the value of <code>x</code> with the
order of its constituent bytes reversed.</td>
</tr>
<tr>
<td valign="top">
@@ -183,7 +183,13 @@ modifiable lvalue of type <code>Reversible</code>.</td>
<p> [<i>Note:</i> A user-defined type meets these requirements by defining a
non-member function in the same namespace as the UDT itself so that the function
can be found by argument dependent lookup (ADL). <i>&mdash;end note</i>]</p>
can be found by argument dependent lookup (ADL).&nbsp; <i>&mdash;end note</i>]</p>
<p> [<i>Note:</i> Because there is a function template for <code>reverse_endianness_in_place</code>
that calls <code>reverse_endianness</code>, only <code>reverse_endianness</code>
is required for a user-defined type to meet the <code>Reversible</code>
requirements. User-defined types may provide <code>reverse_endianness_in_place</code>
for improved efficiency. <i>&mdash;end note</i>]</p>
</blockquote>
@@ -192,13 +198,13 @@ can be found by argument dependent lookup (ADL). <i>&mdash;end note</i>]</p>
<p> This subsection describes requirements on the endian library&#39;s own
implementation.</p>
<p> The endianness conversion function templates that return values are
<p> The endianness reversal function templates that return values are
required to perform reversal of endianness if needed by making an unqualified
call to <code>reverse_endianness(<i>argument</i>)</code>, as described in the
preceding table.</p>
<p> The endianness conversion function templates that modify their argument in
place are required to perform reversal of endianness if needed by making an
<p> The endianness reversal function templates that modify their argument in
place, except <code>reverse_endianness_in_place</code> itself, are required to perform reversal of endianness if needed by making an
unqualified call to <code>reverse_endianness_in_place(<i>argument</i>)</code>,
as described in the preceding table.</p>

View File

@@ -39,7 +39,7 @@ namespace endian
//--------------------------------------------------------------------------------------//
// //
// return-by-value interfaces //
// return-by-value suggested by Phil Endecott //
// suggested by Phil Endecott //
// //
// user-defined types (UDTs) //
// //
@@ -128,17 +128,10 @@ namespace endian
// //
//------------------------------------------------------------------------------------//
// customization for built-in arithmetic types
inline void reverse_endianness_in_place(int8_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(int16_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(int32_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(int64_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(uint8_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(uint16_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(uint32_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(uint64_t& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(float& x) BOOST_NOEXCEPT;
inline void reverse_endianness_in_place(double& x) BOOST_NOEXCEPT;
// reverse in place
template <class Value>
inline void reverse_endianness_in_place(Value& x) BOOST_NOEXCEPT;
// Effects: x = reverse_endianness(x)
// reverse in place unless native endianness is big
template <class Reversible>
@@ -413,27 +406,12 @@ namespace endian
// reverse-in-place implementation //
//--------------------------------------------------------------------------------------//
// customization for built-in arithmetic types
inline void reverse_endianness_in_place(int8_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(int16_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(int32_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(int64_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(uint8_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(uint16_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(uint32_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(uint64_t& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(float& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
inline void reverse_endianness_in_place(double& x) BOOST_NOEXCEPT
{ x = reverse_endianness(x); }
// reverse in place
template <class Value>
inline void reverse_endianness_in_place(Value& x) BOOST_NOEXCEPT
{
x = reverse_endianness(x);
}
// reverse in place unless native endianness is big
// Effects: none if native endian order is big,

View File

@@ -260,37 +260,107 @@ namespace
BOOST_TEST_EQ(x, little);
}
//--------------------------------------------------------------------------------------//
template <class UDT>
void udt_test()
{
UDT udt, tmp;
int64_t big;
int64_t little;
int64_t native;
big_value(big);
little_value(little);
native_value(native);
udt.member1 = big;
udt.member2 = little;
udt.member3 = native;
tmp = be::conditional_reverse<be::order::big, be::order::little>(udt);
BOOST_TEST_EQ(tmp.member1, be::reverse_endianness(big));
BOOST_TEST_EQ(tmp.member2, be::reverse_endianness(little));
BOOST_TEST_EQ(tmp.member3, be::reverse_endianness(native));
be::conditional_reverse_in_place<be::order::big, be::order::little>(udt);
BOOST_TEST_EQ(udt.member1, be::reverse_endianness(big));
BOOST_TEST_EQ(udt.member2, be::reverse_endianness(little));
BOOST_TEST_EQ(udt.member3, be::reverse_endianness(native));
udt.member1 = big;
udt.member2 = little;
udt.member3 = native;
tmp.member1 = tmp.member2 = tmp.member3 = 0;
tmp = be::conditional_reverse<be::order::big, be::order::big>(udt);
BOOST_TEST_EQ(tmp.member1, big);
BOOST_TEST_EQ(tmp.member2, little);
BOOST_TEST_EQ(tmp.member3, native);
be::conditional_reverse_in_place<be::order::big, be::order::big>(udt);
BOOST_TEST_EQ(udt.member1, big);
BOOST_TEST_EQ(udt.member2, little);
BOOST_TEST_EQ(udt.member3, native);
}
} // unnamed namespace
//--------------------------------------------------------------------------------------//
// User-defined type
// User-defined types
namespace user
{
struct UDT
// UDT1 supplies both reverse_endianness and reverse_endianness_in_place
struct UDT1
{
int64_t member1;
int64_t member2;
int64_t member3;
};
UDT reverse_endianness(const UDT& udt) BOOST_NOEXCEPT
UDT1 reverse_endianness(const UDT1& udt) BOOST_NOEXCEPT
{
UDT tmp;
UDT1 tmp;
tmp.member1 = boost::endian::reverse_endianness(udt.member1);
tmp.member2 = boost::endian::reverse_endianness(udt.member2);
tmp.member3 = boost::endian::reverse_endianness(udt.member3);
return tmp;
}
void reverse_endianness_in_place(UDT& udt) BOOST_NOEXCEPT
void reverse_endianness_in_place(UDT1& udt) BOOST_NOEXCEPT
{
boost::endian::reverse_endianness_in_place(udt.member1);
boost::endian::reverse_endianness_in_place(udt.member2);
boost::endian::reverse_endianness_in_place(udt.member3);
}
// UDT2 supplies only reverse_endianness
struct UDT2
{
int64_t member1;
int64_t member2;
int64_t member3;
};
UDT2 reverse_endianness(const UDT2& udt) BOOST_NOEXCEPT
{
UDT2 tmp;
tmp.member1 = boost::endian::reverse_endianness(udt.member1);
tmp.member2 = boost::endian::reverse_endianness(udt.member2);
tmp.member3 = boost::endian::reverse_endianness(udt.member3);
return tmp;
}
// UDT3 supplies neither reverse_endianness nor reverse_endianness_in_place,
// so udt_test<UDT3>() should fail to compile
struct UDT3
{
int64_t member1;
int64_t member2;
int64_t member3;
};
} // namespace user
//--------------------------------------------------------------------------------------//
@@ -326,30 +396,16 @@ int cpp_main(int, char * [])
cout << "double" << endl;
test<double>();
cout << "UDT" << endl;
user::UDT udt;
int64_t big;
int64_t little;
int64_t native;
big_value(big);
little_value(little);
native_value(native);
cout << "UDT 1" << endl;
udt_test<user::UDT1>();
udt.member1 = big;
udt.member2 = little;
udt.member3 = native;
be::conditional_reverse_in_place<be::order::big, be::order::little>(udt);
BOOST_TEST_EQ(udt.member1, be::reverse_endianness(big));
BOOST_TEST_EQ(udt.member2, be::reverse_endianness(little));
BOOST_TEST_EQ(udt.member3, be::reverse_endianness(native));
cout << "UDT 2" << endl;
udt_test<user::UDT2>();
udt.member1 = big;
udt.member2 = little;
udt.member3 = native;
be::conditional_reverse_in_place<be::order::big, be::order::big>(udt);
BOOST_TEST_EQ(udt.member1, big);
BOOST_TEST_EQ(udt.member2, little);
BOOST_TEST_EQ(udt.member3, native);
#ifdef BOOST_ENDIAN_COMPILE_FAIL
cout << "UDT 3" << endl;
udt_test<user::UDT3>(); // should fail to compile since has not reverse_endianness()
#endif
return ::boost::report_errors();
}