diff --git a/include/boost/units/conversion.hpp b/include/boost/units/conversion.hpp index f5d4a1ef..af479a68 100644 --- a/include/boost/units/conversion.hpp +++ b/include/boost/units/conversion.hpp @@ -20,7 +20,7 @@ namespace boost { namespace units { -template +template struct conversion_helper; #ifdef BOOST_UNITS_DOXYGEN diff --git a/include/boost/units/detail/conversion_impl.hpp b/include/boost/units/detail/conversion_impl.hpp index f3cc1957..b15b3a8b 100644 --- a/include/boost/units/detail/conversion_impl.hpp +++ b/include/boost/units/detail/conversion_impl.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -326,15 +327,30 @@ struct conversion_impl<0> }; }; +template +class has_conversion_factor +{ + typedef char yes[1]; + typedef char no[2]; + + template static yes& test(char(*)[sizeof(conversion_factor(T(), U()))]); + + template static no& test(...); + + public: + enum { value = (sizeof(test(0)) == sizeof(yes)) }; +}; + } // namespace detail /// forward to conversion_factor (intentionally allowing ADL) /// INTERNAL ONLY template -struct conversion_helper, quantity > +struct conversion_helper, quantity, typename boost::enable_if_c::value>::type> { /// INTERNAL ONLY typedef quantity destination_type; + static BOOST_CONSTEXPR destination_type convert(const quantity& source) { return(destination_type::from_value(static_cast(source.value() * conversion_factor(Unit1(), Unit2())))); diff --git a/include/boost/units/quantity.hpp b/include/boost/units/quantity.hpp index c6ae6e73..64ff2037 100644 --- a/include/boost/units/quantity.hpp +++ b/include/boost/units/quantity.hpp @@ -79,11 +79,22 @@ struct disable_if_is_same typedef void type; }; -template -struct disable_if_is_same {}; +template +struct has_conversion_helper +{ + typedef char yes[1]; + typedef char no[2]; + + template static yes& test(char(*)[sizeof(conversion_helper)]); + + template static no& test(...); + + public: + enum { value = (sizeof(test(0)) == sizeof(yes)) }; +}; } - + /// class declaration template class quantity @@ -178,9 +189,10 @@ class quantity #ifndef BOOST_NO_SFINAE /// explicit conversion between different unit systems is allowed if implicit conversion is disallowed - template + template explicit - BOOST_CONSTEXPR quantity(const quantity& source, + BOOST_CONSTEXPR quantity(const quantity& source, + typename boost::enable_if_c,this_type>::value>::type* = 0, typename boost::disable_if< mpl::and_< //is_implicitly_convertible should be undefined when the diff --git a/include/boost/units/units_fwd.hpp b/include/boost/units/units_fwd.hpp index cca5c0b1..abf25c24 100644 --- a/include/boost/units/units_fwd.hpp +++ b/include/boost/units/units_fwd.hpp @@ -56,7 +56,7 @@ template struct is_quantity; template struct is_quantity_of_dimension; template struct is_quantity_of_system; -template struct conversion_helper; +template struct conversion_helper; template std::string to_string(const T&); template std::string name_string(const T&); diff --git a/test/test_conversion.cpp b/test/test_conversion.cpp index 17015245..5c5cbb9a 100644 --- a/test/test_conversion.cpp +++ b/test/test_conversion.cpp @@ -24,6 +24,10 @@ Test conversion between quantities. #include #include #include +#include +#include +#include +#include #include @@ -108,3 +112,11 @@ BOOST_AUTO_TEST_CASE(test_dimensionless_conversions) { BOOST_CONSTEXPR_OR_CONST bu::quantity::type> dimensionless_test5(dimensionless_test4); BOOST_UNITS_CHECK_CLOSE(dimensionless_test5.value(), 2e5); } + +BOOST_AUTO_TEST_CASE(test_unrelated_constructible) { + typedef boost::units::quantity liter; + typedef boost::units::quantity minute; + typedef boost::units::quantity second; + BOOST_CHECK((!boost::is_constructible::value)); + BOOST_CHECK((boost::is_constructible::value)); +}