diff --git a/include/boost/endian/converters.hpp b/include/boost/endian/converters.hpp index b91a3a2..bfa1df1 100644 --- a/include/boost/endian/converters.hpp +++ b/include/boost/endian/converters.hpp @@ -256,93 +256,40 @@ namespace endian # endif } - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return x;} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return x;} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return x;} + namespace detail + { + // Primary template and specializations to support convert_value(). See rationale in convert_value() below. + template + class value_converter ; // primary template + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return x;}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return x;}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return x;}}; - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return x;} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return x;} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return x;} + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_value(x);}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_value(x);}}; +# ifdef BOOST_BIG_ENDIAN + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return return x;}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_value(x);}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return x;}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_value(x);}}; +# else // BOOST_LITTLE_ENDIAN + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_value(x);}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return x;}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_value(x);}}; + template class value_converter {public: T operator()(T x) BOOST_NOEXCEPT {return x;}}; +# endif + } - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return x;} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return x;} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return x;} - - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return x;} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return x;} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return x;} - - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return x;} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return x;} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return x;} - - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return x;} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return x;} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return x;} - - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return x;} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return x;} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return x;} - - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return x;} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return x;} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return x;} - - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline int16_t convert_value(int16_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline uint16_t convert_value(uint16_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline int32_t convert_value(int32_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline uint32_t convert_value(uint32_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline int64_t convert_value(int64_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline uint64_t convert_value(uint64_t x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline float convert_value(float x) BOOST_NOEXCEPT {return little_endian_value(x);} - - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return reverse_value(x);} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return little_endian_value(x);} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return big_endian_value(x);} - template<> inline double convert_value(double x) BOOST_NOEXCEPT {return little_endian_value(x);} + // compile-time generic convert_valuereturn by value + template + Reversible convert_value(Reversible x) BOOST_NOEXCEPT + { + // work around lack of function template partial specialization by instantiating + // a function object of a class that is partially specialized on the two order + // template parameters, and then calling its operator(). + detail::value_converter tmp; + return tmp(x); + } inline BOOST_SCOPED_ENUM(order) actual_order(BOOST_SCOPED_ENUM(order) o) BOOST_NOEXCEPT { @@ -400,96 +347,42 @@ namespace endian # endif } - // compile-time generic byte order conversion - template<> inline void convert(int16_t&) BOOST_NOEXCEPT {} - template<> inline void convert(int16_t&) BOOST_NOEXCEPT {} - template<> inline void convert(int16_t&) BOOST_NOEXCEPT {} + namespace detail + { + // Primary template and specializations to support convert(). See rationale in convert() below. + template + class converter; // primary template + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; - template<> inline void convert(uint16_t&) BOOST_NOEXCEPT {} - template<> inline void convert(uint16_t&) BOOST_NOEXCEPT {} - template<> inline void convert(uint16_t&) BOOST_NOEXCEPT {} + template class converter {public: void operator()(T& x) BOOST_NOEXCEPT {reverse(x);}}; + template class converter {public: void operator()(T& x) BOOST_NOEXCEPT {reverse(x);}}; +# ifdef BOOST_BIG_ENDIAN + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; + template class converter {public: void operator()(T& x) BOOST_NOEXCEPT {reverse(x);}}; + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; + template class converter {public: void operator()(T& x) BOOST_NOEXCEPT {reverse(x);}}; +# else // BOOST_LITTLE_ENDIAN + template class converter {public: void operator()(T& x) BOOST_NOEXCEPT {reverse(x);}}; + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; + template class converter {public: void operator()(T& x) BOOST_NOEXCEPT {reverse(x);}}; + template class converter {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}}; +# endif + } - template<> inline void convert(int32_t&) BOOST_NOEXCEPT {} - template<> inline void convert(int32_t&) BOOST_NOEXCEPT {} - template<> inline void convert(int32_t&) BOOST_NOEXCEPT {} + // compile-time generic byte-order convert in place + template + void convert(Reversible& x) BOOST_NOEXCEPT + { + // work around lack of function template partial specialization by instantiating + // a function object of a class that is partially specialized on the two order + // template parameters, and then calling its operator(). + detail::converter tmp; + tmp(x); + } - template<> inline void convert(uint32_t&) BOOST_NOEXCEPT {} - template<> inline void convert(uint32_t&) BOOST_NOEXCEPT {} - template<> inline void convert(uint32_t&) BOOST_NOEXCEPT {} - - template<> inline void convert(int64_t&) BOOST_NOEXCEPT {} - template<> inline void convert(int64_t&) BOOST_NOEXCEPT {} - template<> inline void convert(int64_t&) BOOST_NOEXCEPT {} - - template<> inline void convert(uint64_t&) BOOST_NOEXCEPT {} - template<> inline void convert(uint64_t&) BOOST_NOEXCEPT {} - template<> inline void convert(uint64_t&) BOOST_NOEXCEPT {} - - template<> inline void convert(float&) BOOST_NOEXCEPT {} - template<> inline void convert(float&) BOOST_NOEXCEPT {} - template<> inline void convert(float&) BOOST_NOEXCEPT {} - - template<> inline void convert(double&) BOOST_NOEXCEPT {} - template<> inline void convert(double&) BOOST_NOEXCEPT {} - template<> inline void convert(double&) BOOST_NOEXCEPT {} - - template<> inline void convert(int16_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(int16_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(int16_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(int16_t& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(int16_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(int16_t& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(uint16_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(uint16_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(uint16_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(uint16_t& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(uint16_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(uint16_t& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(int32_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(int32_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(int32_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(int32_t& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(int32_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(int32_t& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(uint32_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(uint32_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(uint32_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(uint32_t& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(uint32_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(uint32_t& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(int64_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(int64_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(int64_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(int64_t& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(int64_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(int64_t& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(uint64_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(uint64_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(uint64_t& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(uint64_t& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(uint64_t& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(uint64_t& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(float& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(float& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(float& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(float& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(float& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(float& x) BOOST_NOEXCEPT {little_endian(x);} - - template<> inline void convert(double& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(double& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(double& x) BOOST_NOEXCEPT {reverse(x);} - template<> inline void convert(double& x) BOOST_NOEXCEPT {little_endian(x);} - template<> inline void convert(double& x) BOOST_NOEXCEPT {big_endian(x);} - template<> inline void convert(double& x) BOOST_NOEXCEPT {little_endian(x);} - - // runtime byte-order conversion + // runtime byte-order convert in place template void convert(Reversible& x, BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT diff --git a/test/pair_test.cpp b/test/pair_test.cpp index 2942e01..7c851e2 100644 --- a/test/pair_test.cpp +++ b/test/pair_test.cpp @@ -76,6 +76,11 @@ int cpp_main(int, char * []) cout << " big: " << y; cout << "little: " << z << endl; + cout << " big: " << y; + convert(y); + cout << "little: " << y << endl; + convert(y); + return ::boost::report_errors(); }