Move Approx's validity checks out of line into cpp file

This avoids having to include <stdexcept> in the main include path
and speeds up the compilation if Approx is used with multiple
different types.
This commit is contained in:
Martin Hořeňovský 2018-09-03 10:15:49 +02:00
parent fcd91c7d6b
commit 84fa76e985
2 changed files with 31 additions and 17 deletions

View File

@ -10,6 +10,7 @@
#include <cmath> #include <cmath>
#include <limits> #include <limits>
#include <stdexcept>
namespace { namespace {
@ -54,6 +55,27 @@ namespace Detail {
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
} }
void Approx::setMargin(double margin) {
if (margin < 0) {
throw std::domain_error
("Invalid Approx::margin: " +
Catch::Detail::stringify(margin) +
", Approx::Margin has to be non-negative.");
}
m_margin = margin;
}
void Approx::setEpsilon(double epsilon) {
if (epsilon < 0 || epsilon > 1.0) {
throw std::domain_error
("Invalid Approx::epsilon: " +
Catch::Detail::stringify(epsilon) +
", Approx::epsilon has to be between 0 and 1");
}
m_epsilon = epsilon;
}
} // end namespace Detail } // end namespace Detail
namespace literals { namespace literals {

View File

@ -11,7 +11,6 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include <type_traits> #include <type_traits>
#include <stdexcept>
namespace Catch { namespace Catch {
namespace Detail { namespace Detail {
@ -19,6 +18,12 @@ namespace Detail {
class Approx { class Approx {
private: private:
bool equalityComparisonImpl(double other) const; 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: public:
explicit Approx ( double value ); explicit Approx ( double value );
@ -85,27 +90,14 @@ namespace Detail {
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& epsilon( T const& newEpsilon ) { Approx& epsilon( T const& newEpsilon ) {
double epsilonAsDouble = static_cast<double>(newEpsilon); double epsilonAsDouble = static_cast<double>(newEpsilon);
if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) { setEpsilon(epsilonAsDouble);
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; return *this;
} }
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx& margin( T const& newMargin ) { Approx& margin( T const& newMargin ) {
double marginAsDouble = static_cast<double>(newMargin); double marginAsDouble = static_cast<double>(newMargin);
if( marginAsDouble < 0 ) { setMargin(marginAsDouble);
throw std::domain_error
( "Invalid Approx::margin: " +
Catch::Detail::stringify( marginAsDouble ) +
", Approx::Margin has to be non-negative." );
}
m_margin = marginAsDouble;
return *this; return *this;
} }
@ -124,7 +116,7 @@ namespace Detail {
double m_value; double m_value;
}; };
} // end namespace Detail } // end namespace Detail
namespace literals { namespace literals {
Detail::Approx operator "" _a(long double val); Detail::Approx operator "" _a(long double val);
Detail::Approx operator "" _a(unsigned long long val); Detail::Approx operator "" _a(unsigned long long val);