forked from catchorg/Catch2
		
	This avoids having to include <stdexcept> in the main include path and speeds up the compilation if Approx is used with multiple different types.
		
			
				
	
	
		
			133 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 *  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.epsilon( m_epsilon );
 | 
						|
            approx.margin( m_margin );
 | 
						|
            approx.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
 |