mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 00:51:52 +01:00 
			
		
		
		
	ReusableStringStream holds a std::ostringstream internally, but only exposes the ostream interface. It caches a pool of ostringstreams in a vector which is currently global, but will be made thread-local. Altogether this should enable both runtime and compile-time benefits. although more work is needed to realise the compile time opportunities.
		
			
				
	
	
		
			134 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			5.0 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>
 | 
						|
#include <stdexcept>
 | 
						|
 | 
						|
namespace Catch {
 | 
						|
namespace Detail {
 | 
						|
 | 
						|
    class Approx {
 | 
						|
    private:
 | 
						|
        bool equalityComparisonImpl(double other) const;
 | 
						|
 | 
						|
    public:
 | 
						|
        explicit Approx ( double value );
 | 
						|
 | 
						|
        static Approx custom();
 | 
						|
 | 
						|
        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);
 | 
						|
            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 <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);
 | 
						|
            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 <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;
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
template<>
 | 
						|
struct StringMaker<Catch::Detail::Approx> {
 | 
						|
    static std::string convert(Catch::Detail::Approx const& value);
 | 
						|
};
 | 
						|
 | 
						|
} // end namespace Catch
 | 
						|
 | 
						|
#endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
 |