Sprinkle some constexpr around to make Jason happy

Most of these will not matter in practice due to C++14 imposing
significant limitations on what else we can make constexpr, and we cannot
have references outliving the constexpr context either way.
This commit is contained in:
Martin Hořeňovský 2024-09-13 11:16:20 +02:00
parent e97ebe62e7
commit 18df97df00
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
23 changed files with 104 additions and 121 deletions

View File

@ -195,7 +195,6 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_random_seed_generation.cpp ${SOURCES_DIR}/internal/catch_random_seed_generation.cpp
${SOURCES_DIR}/internal/catch_reporter_registry.cpp ${SOURCES_DIR}/internal/catch_reporter_registry.cpp
${SOURCES_DIR}/internal/catch_reporter_spec_parser.cpp ${SOURCES_DIR}/internal/catch_reporter_spec_parser.cpp
${SOURCES_DIR}/internal/catch_result_type.cpp
${SOURCES_DIR}/internal/catch_reusable_string_stream.cpp ${SOURCES_DIR}/internal/catch_reusable_string_stream.cpp
${SOURCES_DIR}/internal/catch_run_context.cpp ${SOURCES_DIR}/internal/catch_run_context.cpp
${SOURCES_DIR}/internal/catch_section.cpp ${SOURCES_DIR}/internal/catch_section.cpp

View File

@ -19,7 +19,7 @@ namespace Catch {
int high_mild = 0; // 1.5 to 3 times IQR above Q3 int high_mild = 0; // 1.5 to 3 times IQR above Q3
int high_severe = 0; // more than 3 times IQR above Q3 int high_severe = 0; // more than 3 times IQR above Q3
int total() const { constexpr int total() const {
return low_severe + low_mild + high_mild + high_severe; return low_severe + low_mild + high_mild + high_severe;
} }
}; };

View File

@ -22,26 +22,26 @@ namespace Catch {
static_assert(sizeof(TestCaseProperties) == sizeof(TCP_underlying_type), static_assert(sizeof(TestCaseProperties) == sizeof(TCP_underlying_type),
"The size of the TestCaseProperties is different from the assumed size"); "The size of the TestCaseProperties is different from the assumed size");
TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) { constexpr TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) {
return static_cast<TestCaseProperties>( return static_cast<TestCaseProperties>(
static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs) static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
); );
} }
TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) { constexpr TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) {
lhs = static_cast<TestCaseProperties>( lhs = static_cast<TestCaseProperties>(
static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs) static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
); );
return lhs; return lhs;
} }
TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) { constexpr TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) {
return static_cast<TestCaseProperties>( return static_cast<TestCaseProperties>(
static_cast<TCP_underlying_type>(lhs) & static_cast<TCP_underlying_type>(rhs) static_cast<TCP_underlying_type>(lhs) & static_cast<TCP_underlying_type>(rhs)
); );
} }
bool applies(TestCaseProperties tcp) { constexpr bool applies(TestCaseProperties tcp) {
static_assert(static_cast<TCP_underlying_type>(TestCaseProperties::None) == 0, static_assert(static_cast<TCP_underlying_type>(TestCaseProperties::None) == 0,
"TestCaseProperties::None must be equal to 0"); "TestCaseProperties::None must be equal to 0");
return tcp != TestCaseProperties::None; return tcp != TestCaseProperties::None;
@ -80,7 +80,7 @@ namespace Catch {
return "Anonymous test case " + std::to_string(++counter); return "Anonymous test case " + std::to_string(++counter);
} }
StringRef extractFilenamePart(StringRef filename) { constexpr StringRef extractFilenamePart(StringRef filename) {
size_t lastDot = filename.size(); size_t lastDot = filename.size();
while (lastDot > 0 && filename[lastDot - 1] != '.') { while (lastDot > 0 && filename[lastDot - 1] != '.') {
--lastDot; --lastDot;
@ -98,7 +98,7 @@ namespace Catch {
} }
// Returns the upper bound on size of extra tags ([#file]+[.]) // Returns the upper bound on size of extra tags ([#file]+[.])
size_t sizeOfExtraTags(StringRef filepath) { constexpr size_t sizeOfExtraTags(StringRef filepath) {
// [.] is 3, [#] is another 3 // [.] is 3, [#] is another 3
const size_t extras = 3 + 3; const size_t extras = 3 + 3;
return extractFilenamePart(filepath).size() + extras; return extractFilenamePart(filepath).size() + extras;
@ -259,8 +259,4 @@ namespace Catch {
return lhs.tags < rhs.tags; return lhs.tags < rhs.tags;
} }
TestCaseInfo const& TestCaseHandle::getTestCaseInfo() const {
return *m_info;
}
} // end namespace Catch } // end namespace Catch

View File

@ -109,7 +109,7 @@ namespace Catch {
TestCaseInfo* m_info; TestCaseInfo* m_info;
ITestInvoker* m_invoker; ITestInvoker* m_invoker;
public: public:
TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) : constexpr TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
m_info(info), m_invoker(invoker) {} m_info(info), m_invoker(invoker) {}
void prepareTestCase() const { void prepareTestCase() const {
@ -124,7 +124,9 @@ namespace Catch {
m_invoker->invoke(); m_invoker->invoke();
} }
TestCaseInfo const& getTestCaseInfo() const; constexpr TestCaseInfo const& getTestCaseInfo() const {
return *m_info;
}
}; };
Detail::unique_ptr<TestCaseInfo> Detail::unique_ptr<TestCaseInfo>

View File

@ -25,7 +25,7 @@ namespace Catch {
class ExceptionTranslator : public IExceptionTranslator { class ExceptionTranslator : public IExceptionTranslator {
public: public:
ExceptionTranslator( std::string(*translateFunction)( T const& ) ) constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) )
: m_translateFunction( translateFunction ) : m_translateFunction( translateFunction )
{} {}

View File

@ -42,7 +42,7 @@ namespace Catch {
template<typename T> template<typename T>
void handleExpr( ExprLhs<T> const& expr ) { constexpr void handleExpr( ExprLhs<T> const& expr ) {
handleExpr( expr.makeUnaryExpr() ); handleExpr( expr.makeUnaryExpr() );
} }
void handleExpr( ITransientExpression const& expr ); void handleExpr( ITransientExpression const& expr );

View File

@ -27,12 +27,6 @@ namespace Catch {
return *Context::currentContext; return *Context::currentContext;
} }
void Context::setResultCapture( IResultCapture* resultCapture ) {
m_resultCapture = resultCapture;
}
void Context::setConfig( IConfig const* config ) { m_config = config; }
SimplePcg32& sharedRng() { SimplePcg32& sharedRng() {
static SimplePcg32 s_rng; static SimplePcg32 s_rng;
return s_rng; return s_rng;

View File

@ -26,10 +26,15 @@ namespace Catch {
friend void cleanUpContext(); friend void cleanUpContext();
public: public:
IResultCapture* getResultCapture() const { return m_resultCapture; } constexpr IResultCapture* getResultCapture() const {
IConfig const* getConfig() const { return m_config; } return m_resultCapture;
void setResultCapture( IResultCapture* resultCapture ); }
void setConfig( IConfig const* config ); constexpr IConfig const* getConfig() const { return m_config; }
constexpr void setResultCapture( IResultCapture* resultCapture ) {
m_resultCapture = resultCapture;
}
constexpr void setConfig( IConfig const* config ) { m_config = config; }
}; };
Context& getCurrentMutableContext(); Context& getCurrentMutableContext();

View File

@ -157,6 +157,9 @@ namespace Catch {
bool m_isBinaryExpression; bool m_isBinaryExpression;
bool m_result; bool m_result;
protected:
~ITransientExpression() = default;
public: public:
constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
constexpr auto getResult() const -> bool { return m_result; } constexpr auto getResult() const -> bool { return m_result; }
@ -168,17 +171,13 @@ namespace Catch {
m_result( result ) m_result( result )
{} {}
ITransientExpression() = default; constexpr ITransientExpression( ITransientExpression const& ) = default;
ITransientExpression(ITransientExpression const&) = default; constexpr ITransientExpression& operator=( ITransientExpression const& ) = default;
ITransientExpression& operator=(ITransientExpression const&) = default;
friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) { friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
expr.streamReconstructedExpression(out); expr.streamReconstructedExpression(out);
return out; return out;
} }
protected:
~ITransientExpression() = default;
}; };
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );

View File

@ -18,6 +18,7 @@ namespace Catch {
typename Sentinel, typename Sentinel,
typename T, typename T,
typename Comparator> typename Comparator>
constexpr
ForwardIter find_sentinel( ForwardIter start, ForwardIter find_sentinel( ForwardIter start,
Sentinel sentinel, Sentinel sentinel,
T const& value, T const& value,
@ -33,6 +34,7 @@ namespace Catch {
typename Sentinel, typename Sentinel,
typename T, typename T,
typename Comparator> typename Comparator>
constexpr
std::ptrdiff_t count_sentinel( ForwardIter start, std::ptrdiff_t count_sentinel( ForwardIter start,
Sentinel sentinel, Sentinel sentinel,
T const& value, T const& value,
@ -46,6 +48,7 @@ namespace Catch {
} }
template <typename ForwardIter, typename Sentinel> template <typename ForwardIter, typename Sentinel>
constexpr
std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value, std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
std::ptrdiff_t> std::ptrdiff_t>
sentinel_distance( ForwardIter iter, const Sentinel sentinel ) { sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
@ -58,7 +61,7 @@ namespace Catch {
} }
template <typename ForwardIter> template <typename ForwardIter>
std::ptrdiff_t sentinel_distance( ForwardIter first, constexpr std::ptrdiff_t sentinel_distance( ForwardIter first,
ForwardIter last ) { ForwardIter last ) {
return std::distance( first, last ); return std::distance( first, last );
} }
@ -68,7 +71,7 @@ namespace Catch {
typename ForwardIter2, typename ForwardIter2,
typename Sentinel2, typename Sentinel2,
typename Comparator> typename Comparator>
bool check_element_counts( ForwardIter1 first_1, constexpr bool check_element_counts( ForwardIter1 first_1,
const Sentinel1 end_1, const Sentinel1 end_1,
ForwardIter2 first_2, ForwardIter2 first_2,
const Sentinel2 end_2, const Sentinel2 end_2,
@ -102,7 +105,7 @@ namespace Catch {
typename ForwardIter2, typename ForwardIter2,
typename Sentinel2, typename Sentinel2,
typename Comparator> typename Comparator>
bool is_permutation( ForwardIter1 first_1, constexpr bool is_permutation( ForwardIter1 first_1,
const Sentinel1 end_1, const Sentinel1 end_1,
ForwardIter2 first_2, ForwardIter2 first_2,
const Sentinel2 end_2, const Sentinel2 end_2,

View File

@ -22,13 +22,13 @@ namespace Catch {
ITransientExpression const* m_transientExpression = nullptr; ITransientExpression const* m_transientExpression = nullptr;
bool m_isNegated; bool m_isNegated;
public: public:
LazyExpression( bool isNegated ): constexpr LazyExpression( bool isNegated ):
m_isNegated(isNegated) m_isNegated(isNegated)
{} {}
LazyExpression(LazyExpression const& other) = default; constexpr LazyExpression(LazyExpression const& other) = default;
LazyExpression& operator = ( LazyExpression const& ) = delete; LazyExpression& operator = ( LazyExpression const& ) = delete;
explicit operator bool() const { constexpr explicit operator bool() const {
return m_transientExpression != nullptr; return m_transientExpression != nullptr;
} }

View File

@ -69,7 +69,7 @@ namespace Catch {
struct ExtendedMultResult { struct ExtendedMultResult {
T upper; T upper;
T lower; T lower;
bool operator==( ExtendedMultResult const& rhs ) const { constexpr bool operator==( ExtendedMultResult const& rhs ) const {
return upper == rhs.upper && lower == rhs.lower; return upper == rhs.upper && lower == rhs.lower;
} }
}; };
@ -187,6 +187,7 @@ namespace Catch {
* get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1]) * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1])
*/ */
template <typename OriginalType, typename UnsignedType> template <typename OriginalType, typename UnsignedType>
constexpr
std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType> std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType>
transposeToNaturalOrder( UnsignedType in ) { transposeToNaturalOrder( UnsignedType in ) {
static_assert( static_assert(
@ -207,6 +208,7 @@ namespace Catch {
template <typename OriginalType, template <typename OriginalType,
typename UnsignedType> typename UnsignedType>
constexpr
std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType> std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType>
transposeToNaturalOrder(UnsignedType in) { transposeToNaturalOrder(UnsignedType in) {
static_assert( static_assert(

View File

@ -1,26 +0,0 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_result_type.hpp>
namespace Catch {
bool isOk( ResultWas::OfType resultType ) {
return ( resultType & ResultWas::FailureBit ) == 0;
}
bool isJustInfo( int flags ) {
return flags == ResultWas::Info;
}
ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
}
bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
} // end namespace Catch

View File

@ -33,8 +33,10 @@ namespace Catch {
}; }; }; };
bool isOk( ResultWas::OfType resultType ); constexpr bool isOk( ResultWas::OfType resultType ) {
bool isJustInfo( int flags ); return ( resultType & ResultWas::FailureBit ) == 0;
}
constexpr bool isJustInfo( int flags ) { return flags == ResultWas::Info; }
// ResultDisposition::Flags enum // ResultDisposition::Flags enum
@ -46,11 +48,18 @@ namespace Catch {
SuppressFail = 0x08 // Failures are reported but do not fail the test SuppressFail = 0x08 // Failures are reported but do not fail the test
}; }; }; };
ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); constexpr ResultDisposition::Flags operator|( ResultDisposition::Flags lhs,
ResultDisposition::Flags rhs ) {
return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) |
static_cast<int>( rhs ) );
}
bool shouldContinueOnFailure( int flags ); constexpr bool isFalseTest( int flags ) {
inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } return ( flags & ResultDisposition::FalseTest ) != 0;
bool shouldSuppressFailure( int flags ); }
constexpr bool shouldSuppressFailure( int flags ) {
return ( flags & ResultDisposition::SuppressFail ) != 0;
}
} // end namespace Catch } // end namespace Catch

View File

@ -54,7 +54,7 @@ namespace Catch {
TestType m_testAsFunction; TestType m_testAsFunction;
public: public:
TestInvokerAsFunction( TestType testAsFunction ) noexcept: constexpr TestInvokerAsFunction( TestType testAsFunction ) noexcept:
m_testAsFunction( testAsFunction ) {} m_testAsFunction( testAsFunction ) {}
void invoke() const override { m_testAsFunction(); } void invoke() const override { m_testAsFunction(); }

View File

@ -32,7 +32,8 @@ template<typename C>
class TestInvokerAsMethod : public ITestInvoker { class TestInvokerAsMethod : public ITestInvoker {
void (C::*m_testAsMethod)(); void (C::*m_testAsMethod)();
public: public:
TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} constexpr TestInvokerAsMethod( void ( C::*testAsMethod )() ) noexcept:
m_testAsMethod( testAsMethod ) {}
void invoke() const override { void invoke() const override {
C obj; C obj;
@ -53,7 +54,8 @@ class TestInvokerFixture : public ITestInvoker {
Detail::unique_ptr<C> m_fixture = nullptr; Detail::unique_ptr<C> m_fixture = nullptr;
public: public:
TestInvokerFixture( void ( C::*testAsMethod )() const) noexcept : m_testAsMethod( testAsMethod ) {} constexpr TestInvokerFixture( void ( C::*testAsMethod )() const ) noexcept:
m_testAsMethod( testAsMethod ) {}
void prepareTestCase() override { void prepareTestCase() override {
m_fixture = Detail::make_unique<C>(); m_fixture = Detail::make_unique<C>();

View File

@ -48,24 +48,24 @@ class uniform_integer_distribution {
// distribution will be reused many times and this is an optimization. // distribution will be reused many times and this is an optimization.
UnsignedIntegerType m_rejection_threshold = 0; UnsignedIntegerType m_rejection_threshold = 0;
UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) const { static constexpr UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) {
// This overflows and returns 0 if a == 0 and b == TYPE_MAX. // This overflows and returns 0 if a == 0 and b == TYPE_MAX.
// We handle that later when generating the number. // We handle that later when generating the number.
return transposeTo(b) - transposeTo(a) + 1; return transposeTo(b) - transposeTo(a) + 1;
} }
static UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) { static constexpr UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
// distance == 0 means that we will return all possible values from // distance == 0 means that we will return all possible values from
// the type's range, and that we shouldn't reject anything. // the type's range, and that we shouldn't reject anything.
if ( ab_distance == 0 ) { return 0; } if ( ab_distance == 0 ) { return 0; }
return ( ~ab_distance + 1 ) % ab_distance; return ( ~ab_distance + 1 ) % ab_distance;
} }
static UnsignedIntegerType transposeTo(IntegerType in) { static constexpr UnsignedIntegerType transposeTo(IntegerType in) {
return Detail::transposeToNaturalOrder<IntegerType>( return Detail::transposeToNaturalOrder<IntegerType>(
static_cast<UnsignedIntegerType>( in ) ); static_cast<UnsignedIntegerType>( in ) );
} }
static IntegerType transposeBack(UnsignedIntegerType in) { static constexpr IntegerType transposeBack(UnsignedIntegerType in) {
return static_cast<IntegerType>( return static_cast<IntegerType>(
Detail::transposeToNaturalOrder<IntegerType>(in) ); Detail::transposeToNaturalOrder<IntegerType>(in) );
} }
@ -73,7 +73,7 @@ class uniform_integer_distribution {
public: public:
using result_type = IntegerType; using result_type = IntegerType;
uniform_integer_distribution( IntegerType a, IntegerType b ): constexpr uniform_integer_distribution( IntegerType a, IntegerType b ):
m_a( transposeTo(a) ), m_a( transposeTo(a) ),
m_ab_distance( computeDistance(a, b) ), m_ab_distance( computeDistance(a, b) ),
m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) { m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) {
@ -81,7 +81,7 @@ public:
} }
template <typename Generator> template <typename Generator>
result_type operator()( Generator& g ) { constexpr result_type operator()( Generator& g ) {
// All possible values of result_type are valid. // All possible values of result_type are valid.
if ( m_ab_distance == 0 ) { if ( m_ab_distance == 0 ) {
return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) ); return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) );
@ -99,8 +99,8 @@ public:
return transposeBack(m_a + emul.upper); return transposeBack(m_a + emul.upper);
} }
result_type a() const { return transposeBack(m_a); } constexpr result_type a() const { return transposeBack(m_a); }
result_type b() const { return transposeBack(m_ab_distance + m_a - 1); } constexpr result_type b() const { return transposeBack(m_ab_distance + m_a - 1); }
}; };
} // end namespace Catch } // end namespace Catch

View File

@ -53,36 +53,16 @@ namespace {
os.flags(f); os.flags(f);
} }
bool shouldNewline(XmlFormatting fmt) { constexpr bool shouldNewline(XmlFormatting fmt) {
return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Newline)); return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Newline));
} }
bool shouldIndent(XmlFormatting fmt) { constexpr bool shouldIndent(XmlFormatting fmt) {
return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Indent)); return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Indent));
} }
} // anonymous namespace } // anonymous namespace
XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) {
return static_cast<XmlFormatting>(
static_cast<std::underlying_type_t<XmlFormatting>>(lhs) |
static_cast<std::underlying_type_t<XmlFormatting>>(rhs)
);
}
XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) {
return static_cast<XmlFormatting>(
static_cast<std::underlying_type_t<XmlFormatting>>(lhs) &
static_cast<std::underlying_type_t<XmlFormatting>>(rhs)
);
}
XmlEncode::XmlEncode( StringRef str, ForWhat forWhat )
: m_str( str ),
m_forWhat( forWhat )
{}
void XmlEncode::encodeTo( std::ostream& os ) const { void XmlEncode::encodeTo( std::ostream& os ) const {
// Apostrophe escaping not necessary if we always use " to write attributes // Apostrophe escaping not necessary if we always use " to write attributes
// (see: http://www.w3.org/TR/xml/#syntax) // (see: http://www.w3.org/TR/xml/#syntax)

View File

@ -15,14 +15,22 @@
#include <vector> #include <vector>
namespace Catch { namespace Catch {
enum class XmlFormatting { enum class XmlFormatting : uint8_t {
None = 0x00, None = 0x00,
Indent = 0x01, Indent = 0x01,
Newline = 0x02, Newline = 0x02,
}; };
XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); constexpr XmlFormatting operator|( XmlFormatting lhs, XmlFormatting rhs ) {
XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); return static_cast<XmlFormatting>( static_cast<uint8_t>( lhs ) |
static_cast<uint8_t>( rhs ) );
}
constexpr XmlFormatting operator&( XmlFormatting lhs, XmlFormatting rhs ) {
return static_cast<XmlFormatting>( static_cast<uint8_t>( lhs ) &
static_cast<uint8_t>( rhs ) );
}
/** /**
* Helper for XML-encoding text (escaping angle brackets, quotes, etc) * Helper for XML-encoding text (escaping angle brackets, quotes, etc)
@ -34,7 +42,9 @@ namespace Catch {
public: public:
enum ForWhat { ForTextNodes, ForAttributes }; enum ForWhat { ForTextNodes, ForAttributes };
XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ); constexpr XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ):
m_str( str ), m_forWhat( forWhat ) {}
void encodeTo( std::ostream& os ) const; void encodeTo( std::ostream& os ) const;

View File

@ -28,12 +28,14 @@ namespace Catch {
public: public:
template <typename TargetRangeLike2, typename Equality2> template <typename TargetRangeLike2, typename Equality2>
constexpr
RangeEqualsMatcher( TargetRangeLike2&& range, RangeEqualsMatcher( TargetRangeLike2&& range,
Equality2&& predicate ): Equality2&& predicate ):
m_desired( CATCH_FORWARD( range ) ), m_desired( CATCH_FORWARD( range ) ),
m_predicate( CATCH_FORWARD( predicate ) ) {} m_predicate( CATCH_FORWARD( predicate ) ) {}
template <typename RangeLike> template <typename RangeLike>
constexpr
bool match( RangeLike&& rng ) const { bool match( RangeLike&& rng ) const {
auto rng_start = begin( rng ); auto rng_start = begin( rng );
const auto rng_end = end( rng ); const auto rng_end = end( rng );
@ -66,12 +68,14 @@ namespace Catch {
public: public:
template <typename TargetRangeLike2, typename Equality2> template <typename TargetRangeLike2, typename Equality2>
constexpr
UnorderedRangeEqualsMatcher( TargetRangeLike2&& range, UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
Equality2&& predicate ): Equality2&& predicate ):
m_desired( CATCH_FORWARD( range ) ), m_desired( CATCH_FORWARD( range ) ),
m_predicate( CATCH_FORWARD( predicate ) ) {} m_predicate( CATCH_FORWARD( predicate ) ) {}
template <typename RangeLike> template <typename RangeLike>
constexpr
bool match( RangeLike&& rng ) const { bool match( RangeLike&& rng ) const {
using std::begin; using std::begin;
using std::end; using std::end;
@ -95,6 +99,7 @@ namespace Catch {
* Uses `std::equal_to` to do the comparison * Uses `std::equal_to` to do the comparison
*/ */
template <typename RangeLike> template <typename RangeLike>
constexpr
std::enable_if_t<!Detail::is_matcher<RangeLike>::value, std::enable_if_t<!Detail::is_matcher<RangeLike>::value,
RangeEqualsMatcher<RangeLike, std::equal_to<>>> RangeEqualsMatcher<RangeLike, std::equal_to<>>>
RangeEquals( RangeLike&& range ) { RangeEquals( RangeLike&& range ) {
@ -108,6 +113,7 @@ namespace Catch {
* Uses to provided predicate `predicate` to do the comparisons * Uses to provided predicate `predicate` to do the comparisons
*/ */
template <typename RangeLike, typename Equality> template <typename RangeLike, typename Equality>
constexpr
RangeEqualsMatcher<RangeLike, Equality> RangeEqualsMatcher<RangeLike, Equality>
RangeEquals( RangeLike&& range, Equality&& predicate ) { RangeEquals( RangeLike&& range, Equality&& predicate ) {
return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
@ -120,6 +126,7 @@ namespace Catch {
* Uses `std::equal_to` to do the comparison * Uses `std::equal_to` to do the comparison
*/ */
template <typename RangeLike> template <typename RangeLike>
constexpr
std::enable_if_t< std::enable_if_t<
!Detail::is_matcher<RangeLike>::value, !Detail::is_matcher<RangeLike>::value,
UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>> UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>>
@ -134,6 +141,7 @@ namespace Catch {
* Uses to provided predicate `predicate` to do the comparisons * Uses to provided predicate `predicate` to do the comparisons
*/ */
template <typename RangeLike, typename Equality> template <typename RangeLike, typename Equality>
constexpr
UnorderedRangeEqualsMatcher<RangeLike, Equality> UnorderedRangeEqualsMatcher<RangeLike, Equality>
UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) { UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) {
return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };

View File

@ -33,7 +33,7 @@ namespace Catch {
ArgT && m_arg; ArgT && m_arg;
MatcherT const& m_matcher; MatcherT const& m_matcher;
public: public:
MatchExpr( ArgT && arg, MatcherT const& matcher ) constexpr MatchExpr( ArgT && arg, MatcherT const& matcher )
: ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose : ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose
m_arg( CATCH_FORWARD(arg) ), m_arg( CATCH_FORWARD(arg) ),
m_matcher( matcher ) m_matcher( matcher )
@ -63,7 +63,8 @@ namespace Catch {
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ); void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher );
template<typename ArgT, typename MatcherT> template<typename ArgT, typename MatcherT>
auto makeMatchExpr( ArgT && arg, MatcherT const& matcher ) -> MatchExpr<ArgT, MatcherT> { constexpr MatchExpr<ArgT, MatcherT>
makeMatchExpr( ArgT&& arg, MatcherT const& matcher ) {
return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher ); return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher );
} }

View File

@ -234,7 +234,6 @@ internal_sources = files(
'internal/catch_random_seed_generation.cpp', 'internal/catch_random_seed_generation.cpp',
'internal/catch_reporter_registry.cpp', 'internal/catch_reporter_registry.cpp',
'internal/catch_reporter_spec_parser.cpp', 'internal/catch_reporter_spec_parser.cpp',
'internal/catch_result_type.cpp',
'internal/catch_reusable_string_stream.cpp', 'internal/catch_reusable_string_stream.cpp',
'internal/catch_run_context.cpp', 'internal/catch_run_context.cpp',
'internal/catch_section.cpp', 'internal/catch_section.cpp',