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 <code>x</code> is a value of a possibly <code>const</code> type convertible
to <code>Reversible</code>.</td> to <code>Reversible</code>.</td>
<td> <td>
<p>The value of <code>x</code> with the <p>Returns the value of <code>x</code> with the
order of its constituent bytes reversed is returned.</td> order of its constituent bytes reversed.</td>
</tr> </tr>
<tr> <tr>
<td valign="top"> <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 <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 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> </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 <p> This subsection describes requirements on the endian library&#39;s own
implementation.</p> 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 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 call to <code>reverse_endianness(<i>argument</i>)</code>, as described in the
preceding table.</p> preceding table.</p>
<p> The endianness conversion function templates that modify their argument in <p> The endianness reversal function templates that modify their argument in
place are required to perform reversal of endianness if needed by making an 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>, unqualified call to <code>reverse_endianness_in_place(<i>argument</i>)</code>,
as described in the preceding table.</p> as described in the preceding table.</p>

View File

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

View File

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