/* * 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 <type_traits> namespace Catch { namespace Detail { class Approx { private: bool equalityComparisonImpl(double other) const; // Validates the new margin (margin >= 0) // out-of-line to avoid including stdexcept in the header void setMargin(double margin); // Validates the new epsilon (0 < epsilon < 1) // out-of-line to avoid including stdexcept in the header void setEpsilon(double epsilon); public: explicit Approx ( double value ); static Approx custom(); Approx operator-() const; template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx operator()( T const& value ) { Approx approx( static_cast<double>(value) ); approx.m_epsilon = m_epsilon; approx.m_margin = m_margin; approx.m_scale = m_scale; return approx; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> explicit Approx( T const& value ): Approx(static_cast<double>(value)) {} template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { auto lhs_v = static_cast<double>(lhs); return rhs.equalityComparisonImpl(lhs_v); } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator == ( Approx const& lhs, const T& rhs ) { return operator==( rhs, lhs ); } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator != ( T const& lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator != ( Approx const& lhs, T const& rhs ) { return !operator==( rhs, lhs ); } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator <= ( T const& lhs, Approx const& rhs ) { return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator <= ( Approx const& lhs, T const& rhs ) { return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator >= ( T const& lhs, Approx const& rhs ) { return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator >= ( Approx const& lhs, T const& rhs ) { return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx& epsilon( T const& newEpsilon ) { double epsilonAsDouble = static_cast<double>(newEpsilon); setEpsilon(epsilonAsDouble); return *this; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx& margin( T const& newMargin ) { double marginAsDouble = static_cast<double>(newMargin); setMargin(marginAsDouble); return *this; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx& scale( T const& newScale ) { m_scale = static_cast<double>(newScale); return *this; } std::string toString() const; private: double m_epsilon; double m_margin; double m_scale; double m_value; }; } // end namespace Detail namespace literals { Detail::Approx operator "" _a(long double val); Detail::Approx operator "" _a(unsigned long long val); } // end namespace literals template<> struct StringMaker<Catch::Detail::Approx> { static std::string convert(Catch::Detail::Approx const& value); }; } // end namespace Catch #endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED