/* * Created by Phil on 28/04/2011. * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED #include "catch_tostring.h" #include #include namespace Catch { namespace Detail { class Approx { private: bool equalityComparisonImpl(double other) const; public: explicit Approx ( double value ); static Approx custom(); template ::value>::type> Approx operator()( T const& value ) { Approx approx( static_cast(value) ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); approx.scale( m_scale ); return approx; } template ::value>::type> explicit Approx( T const& value ): Approx(static_cast(value)) {} template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { auto lhs_v = static_cast(lhs); return rhs.equalityComparisonImpl(lhs_v); } template ::value>::type> friend bool operator == ( Approx const& lhs, const T& rhs ) { return operator==( rhs, lhs ); } template ::value>::type> friend bool operator != ( T const& lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template ::value>::type> friend bool operator != ( Approx const& lhs, T const& rhs ) { return !operator==( rhs, lhs ); } template ::value>::type> friend bool operator <= ( T const& lhs, Approx const& rhs ) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } template ::value>::type> friend bool operator <= ( Approx const& lhs, T const& rhs ) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } template ::value>::type> friend bool operator >= ( T const& lhs, Approx const& rhs ) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } template ::value>::type> friend bool operator >= ( Approx const& lhs, T const& rhs ) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } template ::value>::type> Approx& epsilon( T const& newEpsilon ) { double epsilonAsDouble = static_cast(newEpsilon); if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) { throw std::domain_error ( "Invalid Approx::epsilon: " + Catch::Detail::stringify( epsilonAsDouble ) + ", Approx::epsilon has to be between 0 and 1" ); } m_epsilon = epsilonAsDouble; return *this; } template ::value>::type> Approx& margin( T const& newMargin ) { double marginAsDouble = static_cast(newMargin); if( marginAsDouble < 0 ) { throw std::domain_error ( "Invalid Approx::margin: " + Catch::Detail::stringify( marginAsDouble ) + ", Approx::Margin has to be non-negative." ); } m_margin = marginAsDouble; return *this; } template ::value>::type> Approx& scale( T const& newScale ) { m_scale = static_cast(newScale); return *this; } std::string toString() const; private: double m_epsilon; double m_margin; double m_scale; double m_value; }; } template<> struct StringMaker { static std::string convert(Catch::Detail::Approx const& value); }; } // end namespace Catch #endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED