Use std::optional

This commit is contained in:
Chris Thrasher
2025-09-21 16:55:09 -06:00
parent db46dc4cb2
commit a5735af2f7
26 changed files with 74 additions and 264 deletions

View File

@@ -84,7 +84,7 @@ namespace Catch {
std::vector<FDuration> samples2; std::vector<FDuration> samples2;
samples2.reserve(samples.size()); samples2.reserve(samples.size());
for (auto s : samples) { for (auto s : samples) {
samples2.emplace_back( s ); samples2.push_back( FDuration( s ) );
} }
return { return {

View File

@@ -101,7 +101,6 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_meta.hpp ${SOURCES_DIR}/internal/catch_meta.hpp
${SOURCES_DIR}/internal/catch_move_and_forward.hpp ${SOURCES_DIR}/internal/catch_move_and_forward.hpp
${SOURCES_DIR}/internal/catch_noncopyable.hpp ${SOURCES_DIR}/internal/catch_noncopyable.hpp
${SOURCES_DIR}/internal/catch_optional.hpp
${SOURCES_DIR}/internal/catch_output_redirect.hpp ${SOURCES_DIR}/internal/catch_output_redirect.hpp
${SOURCES_DIR}/internal/catch_parse_numbers.hpp ${SOURCES_DIR}/internal/catch_parse_numbers.hpp
${SOURCES_DIR}/internal/catch_platform.hpp ${SOURCES_DIR}/internal/catch_platform.hpp

View File

@@ -82,7 +82,6 @@
#include <catch2/internal/catch_meta.hpp> #include <catch2/internal/catch_meta.hpp>
#include <catch2/internal/catch_move_and_forward.hpp> #include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_noncopyable.hpp> #include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_output_redirect.hpp> #include <catch2/internal/catch_output_redirect.hpp>
#include <catch2/internal/catch_parse_numbers.hpp> #include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_platform.hpp> #include <catch2/internal/catch_platform.hpp>

View File

@@ -17,6 +17,7 @@
#include <catch2/internal/catch_getenv.hpp> #include <catch2/internal/catch_getenv.hpp>
#include <fstream> #include <fstream>
#include <optional>
namespace Catch { namespace Catch {
@@ -34,7 +35,7 @@ namespace Catch {
std::string shardFilePath; std::string shardFilePath;
}; };
static Optional<bazelShardingOptions> readBazelShardingOptions() { static std::optional<bazelShardingOptions> readBazelShardingOptions() {
const auto bazelShardIndex = Detail::getEnv( "TEST_SHARD_INDEX" ); const auto bazelShardIndex = Detail::getEnv( "TEST_SHARD_INDEX" );
const auto bazelShardTotal = Detail::getEnv( "TEST_TOTAL_SHARDS" ); const auto bazelShardTotal = Detail::getEnv( "TEST_TOTAL_SHARDS" );
const auto bazelShardInfoFile = Detail::getEnv( "TEST_SHARD_STATUS_FILE" ); const auto bazelShardInfoFile = Detail::getEnv( "TEST_SHARD_STATUS_FILE" );
@@ -142,7 +143,7 @@ namespace Catch {
// We do the default-output check separately, while always // We do the default-output check separately, while always
// using the default output below to make the code simpler // using the default output below to make the code simpler
// and avoid superfluous copies. // and avoid superfluous copies.
if ( reporterSpec.outputFile().none() ) { if ( !reporterSpec.outputFile() ) {
CATCH_ENFORCE( !defaultOutputUsed, CATCH_ENFORCE( !defaultOutputUsed,
"Internal error: cannot use default output for " "Internal error: cannot use default output for "
"multiple reporters" ); "multiple reporters" );
@@ -153,7 +154,7 @@ namespace Catch {
reporterSpec.name(), reporterSpec.name(),
reporterSpec.outputFile() ? *reporterSpec.outputFile() reporterSpec.outputFile() ? *reporterSpec.outputFile()
: data.defaultOutputFilename, : data.defaultOutputFilename,
reporterSpec.colourMode().valueOr( data.defaultColourMode ), reporterSpec.colourMode().value_or( data.defaultColourMode ),
reporterSpec.customOptions() } ); reporterSpec.customOptions() } );
} }
} }

View File

@@ -11,7 +11,6 @@
#include <catch2/catch_test_spec.hpp> #include <catch2/catch_test_spec.hpp>
#include <catch2/interfaces/catch_interfaces_config.hpp> #include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_random_seed_generation.hpp> #include <catch2/internal/catch_random_seed_generation.hpp>
#include <catch2/internal/catch_reporter_spec_parser.hpp> #include <catch2/internal/catch_reporter_spec_parser.hpp>

View File

@@ -88,7 +88,7 @@ namespace Catch {
return ParserResult::ok( ParseResultType::Matched ); return ParserResult::ok( ParseResultType::Matched );
}; };
auto const setDefaultColourMode = [&]( std::string const& colourMode ) { auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode )); std::optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
if ( !maybeMode ) { if ( !maybeMode ) {
return ParserResult::runtimeError( return ParserResult::runtimeError(
"colour mode must be one of: default, ansi, win32, " "colour mode must be one of: default, ansi, win32, "
@@ -135,7 +135,7 @@ namespace Catch {
return ParserResult::runtimeError( "Received empty reporter spec." ); return ParserResult::runtimeError( "Received empty reporter spec." );
} }
Optional<ReporterSpec> parsed = std::optional<ReporterSpec> parsed =
parseReporterSpec( userReporterSpec ); parseReporterSpec( userReporterSpec );
if ( !parsed ) { if ( !parsed ) {
return ParserResult::runtimeError( return ParserResult::runtimeError(
@@ -156,7 +156,7 @@ namespace Catch {
} }
const bool hadOutputFile = reporterSpec.outputFile().some(); const bool hadOutputFile = reporterSpec.outputFile().has_value();
config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) ); config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
// It would be enough to check this only once at the very end, but // It would be enough to check this only once at the very end, but
// there is not a place where we could call this check, so do it // there is not a place where we could call this check, so do it
@@ -165,7 +165,7 @@ namespace Catch {
if (!hadOutputFile) { if (!hadOutputFile) {
int n_reporters_without_file = 0; int n_reporters_without_file = 0;
for (auto const& spec : config.reporterSpecifications) { for (auto const& spec : config.reporterSpecifications) {
if (spec.outputFile().none()) { if (!spec.outputFile()) {
n_reporters_without_file++; n_reporters_without_file++;
} }
} }

View File

@@ -1,117 +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
#ifndef CATCH_OPTIONAL_HPP_INCLUDED
#define CATCH_OPTIONAL_HPP_INCLUDED
#include <catch2/internal/catch_move_and_forward.hpp>
#include <cassert>
namespace Catch {
// An optional type
template<typename T>
class Optional {
public:
Optional(): nullableValue( nullptr ) {}
~Optional() { reset(); }
Optional( T const& _value ):
nullableValue( new ( storage ) T( _value ) ) {}
Optional( T&& _value ):
nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
Optional& operator=( T const& _value ) {
reset();
nullableValue = new ( storage ) T( _value );
return *this;
}
Optional& operator=( T&& _value ) {
reset();
nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
return *this;
}
Optional( Optional const& _other ):
nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
Optional( Optional&& _other ):
nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
: nullptr ) {}
Optional& operator=( Optional const& _other ) {
if ( &_other != this ) {
reset();
if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
}
return *this;
}
Optional& operator=( Optional&& _other ) {
if ( &_other != this ) {
reset();
if ( _other ) {
nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
}
}
return *this;
}
void reset() {
if ( nullableValue ) { nullableValue->~T(); }
nullableValue = nullptr;
}
T& operator*() {
assert(nullableValue);
return *nullableValue;
}
T const& operator*() const {
assert(nullableValue);
return *nullableValue;
}
T* operator->() {
assert(nullableValue);
return nullableValue;
}
const T* operator->() const {
assert(nullableValue);
return nullableValue;
}
T valueOr( T const& defaultValue ) const {
return nullableValue ? *nullableValue : defaultValue;
}
bool some() const { return nullableValue != nullptr; }
bool none() const { return nullableValue == nullptr; }
bool operator !() const { return nullableValue == nullptr; }
explicit operator bool() const {
return some();
}
friend bool operator==(Optional const& a, Optional const& b) {
if (a.none() && b.none()) {
return true;
} else if (a.some() && b.some()) {
return *a == *b;
} else {
return false;
}
}
friend bool operator!=(Optional const& a, Optional const& b) {
return !( a == b );
}
private:
T* nullableValue;
alignas(alignof(T)) char storage[sizeof(T)];
};
} // end namespace Catch
#endif // CATCH_OPTIONAL_HPP_INCLUDED

View File

@@ -12,10 +12,11 @@
#include <limits> #include <limits>
#include <stdexcept> #include <stdexcept>
#include <optional>
namespace Catch { namespace Catch {
Optional<unsigned int> parseUInt(std::string const& input, int base) { std::optional<unsigned int> parseUInt(std::string const& input, int base) {
auto trimmed = trim( input ); auto trimmed = trim( input );
// std::stoull is annoying and accepts numbers starting with '-', // std::stoull is annoying and accepts numbers starting with '-',
// it just negates them into unsigned int // it just negates them into unsigned int

View File

@@ -8,8 +8,7 @@
#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED #ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
#define CATCH_PARSE_NUMBERS_HPP_INCLUDED #define CATCH_PARSE_NUMBERS_HPP_INCLUDED
#include <catch2/internal/catch_optional.hpp> #include <optional>
#include <string> #include <string>
namespace Catch { namespace Catch {
@@ -20,7 +19,7 @@ namespace Catch {
* Effectively a wrapper around std::stoul but with better error checking * Effectively a wrapper around std::stoul but with better error checking
* e.g. "-1" is rejected, instead of being parsed as UINT_MAX. * e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
*/ */
Optional<unsigned int> parseUInt(std::string const& input, int base = 10); std::optional<unsigned int> parseUInt(std::string const& input, int base = 10);
} }
#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED #endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED

View File

@@ -80,7 +80,7 @@ namespace Catch {
return parts; return parts;
} }
Optional<ColourMode> stringToColourMode( StringRef colourMode ) { std::optional<ColourMode> stringToColourMode( StringRef colourMode ) {
if ( colourMode == "default" ) { if ( colourMode == "default" ) {
return ColourMode::PlatformDefault; return ColourMode::PlatformDefault;
} else if ( colourMode == "ansi" ) { } else if ( colourMode == "ansi" ) {
@@ -103,14 +103,14 @@ namespace Catch {
lhs.m_customOptions == rhs.m_customOptions; lhs.m_customOptions == rhs.m_customOptions;
} }
Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ) { std::optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ) {
auto parts = Detail::splitReporterSpec( reporterSpec ); auto parts = Detail::splitReporterSpec( reporterSpec );
assert( parts.size() > 0 && "Split should never return empty vector" ); assert( parts.size() > 0 && "Split should never return empty vector" );
std::map<std::string, std::string> kvPairs; std::map<std::string, std::string> kvPairs;
Optional<std::string> outputFileName; std::optional<std::string> outputFileName;
Optional<ColourMode> colourMode; std::optional<ColourMode> colourMode;
// First part is always reporter name, so we skip it // First part is always reporter name, so we skip it
for ( size_t i = 1; i < parts.size(); ++i ) { for ( size_t i = 1; i < parts.size(); ++i ) {
@@ -161,8 +161,8 @@ namespace Catch {
ReporterSpec::ReporterSpec( ReporterSpec::ReporterSpec(
std::string name, std::string name,
Optional<std::string> outputFileName, std::optional<std::string> outputFileName,
Optional<ColourMode> colourMode, std::optional<ColourMode> colourMode,
std::map<std::string, std::string> customOptions ): std::map<std::string, std::string> customOptions ):
m_name( CATCH_MOVE( name ) ), m_name( CATCH_MOVE( name ) ),
m_outputFileName( CATCH_MOVE( outputFileName ) ), m_outputFileName( CATCH_MOVE( outputFileName ) ),

View File

@@ -9,12 +9,12 @@
#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED #define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
#include <catch2/interfaces/catch_interfaces_config.hpp> #include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <optional>
namespace Catch { namespace Catch {
@@ -24,7 +24,7 @@ namespace Catch {
//! Splits the reporter spec into reporter name and kv-pair options //! Splits the reporter spec into reporter name and kv-pair options
std::vector<std::string> splitReporterSpec( StringRef reporterSpec ); std::vector<std::string> splitReporterSpec( StringRef reporterSpec );
Optional<ColourMode> stringToColourMode( StringRef colourMode ); std::optional<ColourMode> stringToColourMode( StringRef colourMode );
} }
/** /**
@@ -37,8 +37,8 @@ namespace Catch {
*/ */
class ReporterSpec { class ReporterSpec {
std::string m_name; std::string m_name;
Optional<std::string> m_outputFileName; std::optional<std::string> m_outputFileName;
Optional<ColourMode> m_colourMode; std::optional<ColourMode> m_colourMode;
std::map<std::string, std::string> m_customOptions; std::map<std::string, std::string> m_customOptions;
friend bool operator==( ReporterSpec const& lhs, friend bool operator==( ReporterSpec const& lhs,
@@ -51,17 +51,17 @@ namespace Catch {
public: public:
ReporterSpec( ReporterSpec(
std::string name, std::string name,
Optional<std::string> outputFileName, std::optional<std::string> outputFileName,
Optional<ColourMode> colourMode, std::optional<ColourMode> colourMode,
std::map<std::string, std::string> customOptions ); std::map<std::string, std::string> customOptions );
std::string const& name() const { return m_name; } std::string const& name() const { return m_name; }
Optional<std::string> const& outputFile() const { std::optional<std::string> const& outputFile() const {
return m_outputFileName; return m_outputFileName;
} }
Optional<ColourMode> const& colourMode() const { return m_colourMode; } std::optional<ColourMode> const& colourMode() const { return m_colourMode; }
std::map<std::string, std::string> const& customOptions() const { std::map<std::string, std::string> const& customOptions() const {
return m_customOptions; return m_customOptions;
@@ -78,7 +78,7 @@ namespace Catch {
* * empty key/value in an custom kv pair * * empty key/value in an custom kv pair
* * ... * * ...
*/ */
Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ); std::optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec );
} }

View File

@@ -355,7 +355,7 @@ namespace Catch {
// Reset working state. assertion info will be reset after // Reset working state. assertion info will be reset after
// populateReaction is run if it is needed // populateReaction is run if it is needed
m_lastResult = CATCH_MOVE( result ); m_lastResult.emplace(CATCH_MOVE( result ));
} }
void RunContext::notifyAssertionStarted( AssertionInfo const& info ) { void RunContext::notifyAssertionStarted( AssertionInfo const& info ) {

View File

@@ -18,10 +18,10 @@
#include <catch2/internal/catch_test_case_tracker.hpp> #include <catch2/internal/catch_test_case_tracker.hpp>
#include <catch2/catch_assertion_info.hpp> #include <catch2/catch_assertion_info.hpp>
#include <catch2/catch_assertion_result.hpp> #include <catch2/catch_assertion_result.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_move_and_forward.hpp> #include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_thread_support.hpp> #include <catch2/internal/catch_thread_support.hpp>
#include <optional>
#include <string> #include <string>
namespace Catch { namespace Catch {
@@ -144,7 +144,7 @@ namespace Catch {
TestRunInfo m_runInfo; TestRunInfo m_runInfo;
TestCaseHandle const* m_activeTestCase = nullptr; TestCaseHandle const* m_activeTestCase = nullptr;
ITracker* m_testCaseTracker = nullptr; ITracker* m_testCaseTracker = nullptr;
Optional<AssertionResult> m_lastResult; std::optional<AssertionResult> m_lastResult;
IConfig const* m_config; IConfig const* m_config;
Totals m_totals; Totals m_totals;
Detail::AtomicCounts m_atomicAssertionCount; Detail::AtomicCounts m_atomicAssertionCount;

View File

@@ -108,7 +108,6 @@ internal_headers = [
'internal/catch_meta.hpp', 'internal/catch_meta.hpp',
'internal/catch_move_and_forward.hpp', 'internal/catch_move_and_forward.hpp',
'internal/catch_noncopyable.hpp', 'internal/catch_noncopyable.hpp',
'internal/catch_optional.hpp',
'internal/catch_output_redirect.hpp', 'internal/catch_output_redirect.hpp',
'internal/catch_parse_numbers.hpp', 'internal/catch_parse_numbers.hpp',
'internal/catch_platform.hpp', 'internal/catch_platform.hpp',

View File

@@ -42,19 +42,19 @@ namespace Catch {
m_benchmark( benchmark ) {} m_benchmark( benchmark ) {}
bool AssertionOrBenchmarkResult::isAssertion() const { bool AssertionOrBenchmarkResult::isAssertion() const {
return m_assertion.some(); return m_assertion.has_value();
} }
bool AssertionOrBenchmarkResult::isBenchmark() const { bool AssertionOrBenchmarkResult::isBenchmark() const {
return m_benchmark.some(); return m_benchmark.has_value();
} }
AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const { AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const {
assert(m_assertion.some()); assert(m_assertion.has_value());
return *m_assertion; return *m_assertion;
} }
BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const { BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const {
assert(m_benchmark.some()); assert(m_benchmark.has_value());
return *m_benchmark; return *m_benchmark;
} }

View File

@@ -11,8 +11,8 @@
#include <catch2/reporters/catch_reporter_common_base.hpp> #include <catch2/reporters/catch_reporter_common_base.hpp>
#include <catch2/internal/catch_move_and_forward.hpp> #include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -25,8 +25,8 @@ namespace Catch {
// This should really be a variant, but this is much faster // This should really be a variant, but this is much faster
// to write and the data layout here is already terrible // to write and the data layout here is already terrible
// enough that we do not have to care about the object size. // enough that we do not have to care about the object size.
Optional<AssertionStats> m_assertion; std::optional<AssertionStats> m_assertion;
Optional<BenchmarkStats<>> m_benchmark; std::optional<BenchmarkStats<>> m_benchmark;
public: public:
AssertionOrBenchmarkResult(AssertionStats const& assertion); AssertionOrBenchmarkResult(AssertionStats const& assertion);
AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark); AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark);

View File

@@ -1364,10 +1364,10 @@ Matchers.tests.cpp:<line number>: passed: ( EvilMatcher(), EvilMatcher() ), Evil
Matchers.tests.cpp:<line number>: passed: &EvilMatcher(), EvilAddressOfOperatorUsed Matchers.tests.cpp:<line number>: passed: &EvilMatcher(), EvilAddressOfOperatorUsed
Matchers.tests.cpp:<line number>: passed: EvilMatcher() || ( EvilMatcher() && !EvilMatcher() ) Matchers.tests.cpp:<line number>: passed: EvilMatcher() || ( EvilMatcher() && !EvilMatcher() )
Matchers.tests.cpp:<line number>: passed: ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher() Matchers.tests.cpp:<line number>: passed: ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher()
Parse.tests.cpp:<line number>: passed: parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "0" ) == std::optional<unsigned int>{ 0 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "100" ) == std::optional<unsigned int>{ 100 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "4294967295" ) == std::optional<unsigned int>{ 4294967295 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "0x<hex digits>", 16 ) == std::optional<unsigned int>{ 255 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "" )) for: !{?} Parse.tests.cpp:<line number>: passed: !(parseUInt( "" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "!!KJHF*#" )) for: !{?} Parse.tests.cpp:<line number>: passed: !(parseUInt( "!!KJHF*#" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "-1" )) for: !{?} Parse.tests.cpp:<line number>: passed: !(parseUInt( "-1" )) for: !{?}

View File

@@ -1362,10 +1362,10 @@ Matchers.tests.cpp:<line number>: passed: ( EvilMatcher(), EvilMatcher() ), Evil
Matchers.tests.cpp:<line number>: passed: &EvilMatcher(), EvilAddressOfOperatorUsed Matchers.tests.cpp:<line number>: passed: &EvilMatcher(), EvilAddressOfOperatorUsed
Matchers.tests.cpp:<line number>: passed: EvilMatcher() || ( EvilMatcher() && !EvilMatcher() ) Matchers.tests.cpp:<line number>: passed: EvilMatcher() || ( EvilMatcher() && !EvilMatcher() )
Matchers.tests.cpp:<line number>: passed: ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher() Matchers.tests.cpp:<line number>: passed: ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher()
Parse.tests.cpp:<line number>: passed: parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "0" ) == std::optional<unsigned int>{ 0 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "100" ) == std::optional<unsigned int>{ 100 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "4294967295" ) == std::optional<unsigned int>{ 4294967295 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?} Parse.tests.cpp:<line number>: passed: parseUInt( "0x<hex digits>", 16 ) == std::optional<unsigned int>{ 255 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "" )) for: !{?} Parse.tests.cpp:<line number>: passed: !(parseUInt( "" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "!!KJHF*#" )) for: !{?} Parse.tests.cpp:<line number>: passed: !(parseUInt( "!!KJHF*#" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "-1" )) for: !{?} Parse.tests.cpp:<line number>: passed: !(parseUInt( "-1" )) for: !{?}

View File

@@ -8848,22 +8848,22 @@ Parse.tests.cpp:<line number>
............................................................................... ...............................................................................
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0" ) == Optional<unsigned int>{ 0 } ) REQUIRE( parseUInt( "0" ) == std::optional<unsigned int>{ 0 } )
with expansion: with expansion:
{?} == {?} {?} == {?}
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "100" ) == Optional<unsigned int>{ 100 } ) REQUIRE( parseUInt( "100" ) == std::optional<unsigned int>{ 100 } )
with expansion: with expansion:
{?} == {?} {?} == {?}
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } ) REQUIRE( parseUInt( "4294967295" ) == std::optional<unsigned int>{ 4294967295 } )
with expansion: with expansion:
{?} == {?} {?} == {?}
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } ) REQUIRE( parseUInt( "0x<hex digits>", 16 ) == std::optional<unsigned int>{ 255 } )
with expansion: with expansion:
{?} == {?} {?} == {?}

View File

@@ -8846,22 +8846,22 @@ Parse.tests.cpp:<line number>
............................................................................... ...............................................................................
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0" ) == Optional<unsigned int>{ 0 } ) REQUIRE( parseUInt( "0" ) == std::optional<unsigned int>{ 0 } )
with expansion: with expansion:
{?} == {?} {?} == {?}
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "100" ) == Optional<unsigned int>{ 100 } ) REQUIRE( parseUInt( "100" ) == std::optional<unsigned int>{ 100 } )
with expansion: with expansion:
{?} == {?} {?} == {?}
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } ) REQUIRE( parseUInt( "4294967295" ) == std::optional<unsigned int>{ 4294967295 } )
with expansion: with expansion:
{?} == {?} {?} == {?}
Parse.tests.cpp:<line number>: PASSED: Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } ) REQUIRE( parseUInt( "0x<hex digits>", 16 ) == std::optional<unsigned int>{ 255 } )
with expansion: with expansion:
{?} == {?} {?} == {?}

View File

@@ -2207,13 +2207,13 @@ ok {test-number} - EvilMatcher() || ( EvilMatcher() && !EvilMatcher() )
# Overloaded comma or address-of operators are not used # Overloaded comma or address-of operators are not used
ok {test-number} - ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher() ok {test-number} - ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher()
# Parse uints # Parse uints
ok {test-number} - parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?} ok {test-number} - parseUInt( "0" ) == std::optional<unsigned int>{ 0 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?} ok {test-number} - parseUInt( "100" ) == std::optional<unsigned int>{ 100 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?} ok {test-number} - parseUInt( "4294967295" ) == std::optional<unsigned int>{ 4294967295 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?} ok {test-number} - parseUInt( "0x<hex digits>", 16 ) == std::optional<unsigned int>{ 255 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - !(parseUInt( "" )) for: !{?} ok {test-number} - !(parseUInt( "" )) for: !{?}
# Parse uints # Parse uints

View File

@@ -2205,13 +2205,13 @@ ok {test-number} - EvilMatcher() || ( EvilMatcher() && !EvilMatcher() )
# Overloaded comma or address-of operators are not used # Overloaded comma or address-of operators are not used
ok {test-number} - ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher() ok {test-number} - ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher()
# Parse uints # Parse uints
ok {test-number} - parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?} ok {test-number} - parseUInt( "0" ) == std::optional<unsigned int>{ 0 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?} ok {test-number} - parseUInt( "100" ) == std::optional<unsigned int>{ 100 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?} ok {test-number} - parseUInt( "4294967295" ) == std::optional<unsigned int>{ 4294967295 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?} ok {test-number} - parseUInt( "0x<hex digits>", 16 ) == std::optional<unsigned int>{ 255 } for: {?} == {?}
# Parse uints # Parse uints
ok {test-number} - !(parseUInt( "" )) for: !{?} ok {test-number} - !(parseUInt( "" )) for: !{?}
# Parse uints # Parse uints

View File

@@ -10530,7 +10530,7 @@ Approx( 1.21999999999999997 )
<Section name="proper inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Section name="proper inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "0" ) == Optional&lt;unsigned int>{ 0 } parseUInt( "0" ) == std::optional&lt;unsigned int>{ 0 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}
@@ -10538,7 +10538,7 @@ Approx( 1.21999999999999997 )
</Expression> </Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "100" ) == Optional&lt;unsigned int>{ 100 } parseUInt( "100" ) == std::optional&lt;unsigned int>{ 100 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}
@@ -10546,7 +10546,7 @@ Approx( 1.21999999999999997 )
</Expression> </Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "4294967295" ) == Optional&lt;unsigned int>{ 4294967295 } parseUInt( "4294967295" ) == std::optional&lt;unsigned int>{ 4294967295 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}
@@ -10554,7 +10554,7 @@ Approx( 1.21999999999999997 )
</Expression> </Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "0x<hex digits>", 16 ) == Optional&lt;unsigned int>{ 255 } parseUInt( "0x<hex digits>", 16 ) == std::optional&lt;unsigned int>{ 255 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}

View File

@@ -10530,7 +10530,7 @@ Approx( 1.21999999999999997 )
<Section name="proper inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Section name="proper inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "0" ) == Optional&lt;unsigned int>{ 0 } parseUInt( "0" ) == std::optional&lt;unsigned int>{ 0 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}
@@ -10538,7 +10538,7 @@ Approx( 1.21999999999999997 )
</Expression> </Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "100" ) == Optional&lt;unsigned int>{ 100 } parseUInt( "100" ) == std::optional&lt;unsigned int>{ 100 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}
@@ -10546,7 +10546,7 @@ Approx( 1.21999999999999997 )
</Expression> </Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "4294967295" ) == Optional&lt;unsigned int>{ 4294967295 } parseUInt( "4294967295" ) == std::optional&lt;unsigned int>{ 4294967295 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}
@@ -10554,7 +10554,7 @@ Approx( 1.21999999999999997 )
</Expression> </Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original> <Original>
parseUInt( "0x<hex digits>", 16 ) == Optional&lt;unsigned int>{ 255 } parseUInt( "0x<hex digits>", 16 ) == std::optional&lt;unsigned int>{ 255 }
</Original> </Original>
<Expanded> <Expanded>
{?} == {?} {?} == {?}

View File

@@ -9,7 +9,6 @@
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_enforce.hpp> #include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_case_insensitive_comparisons.hpp> #include <catch2/internal/catch_case_insensitive_comparisons.hpp>
#include <catch2/internal/catch_optional.hpp>
#include <helpers/type_with_lit_0_comparisons.hpp> #include <helpers/type_with_lit_0_comparisons.hpp>
@@ -62,74 +61,6 @@ TEST_CASE( "CaseInsensitiveEqualsTo is case insensitive",
} }
} }
TEST_CASE("Optional comparison ops", "[optional][approvals]") {
using Catch::Optional;
Optional<int> a, b;
SECTION( "Empty optionals are equal" ) {
REQUIRE( a == b );
REQUIRE_FALSE( a != b );
}
SECTION( "Empty and non-empty optionals are never equal" ) {
a = 1;
REQUIRE_FALSE( a == b );
REQUIRE( a != b );
}
SECTION(
"non-empty optionals are equal if the contained elements are equal") {
a = 1;
b = 2;
REQUIRE( a != b );
REQUIRE_FALSE( a == b );
a = 2;
REQUIRE( a == b );
REQUIRE_FALSE( a != b );
}
}
namespace {
struct MoveChecker {
bool has_moved = false;
MoveChecker() = default;
MoveChecker( MoveChecker const& rhs ) = default;
MoveChecker& operator=( MoveChecker const& rhs ) = default;
MoveChecker( MoveChecker&& rhs ) noexcept { rhs.has_moved = true; }
MoveChecker& operator=( MoveChecker&& rhs ) noexcept {
rhs.has_moved = true;
return *this;
}
};
}
TEST_CASE( "Optional supports move ops", "[optional][approvals]" ) {
using Catch::Optional;
MoveChecker a;
Optional<MoveChecker> opt_A( a );
REQUIRE_FALSE( a.has_moved );
REQUIRE_FALSE( opt_A->has_moved );
SECTION( "Move construction from element" ) {
Optional<MoveChecker> opt_B( CATCH_MOVE( a ) );
REQUIRE( a.has_moved );
}
SECTION( "Move assignment from element" ) {
opt_A = CATCH_MOVE( a );
REQUIRE( a.has_moved );
}
SECTION( "Move construction from optional" ) {
Optional<MoveChecker> opt_B( CATCH_MOVE( opt_A ) );
REQUIRE( opt_A->has_moved ); // NOLINT(clang-analyzer-cplusplus.Move)
}
SECTION( "Move assignment from optional" ) {
Optional<MoveChecker> opt_B( opt_A );
REQUIRE_FALSE( opt_A->has_moved );
opt_B = CATCH_MOVE( opt_A );
REQUIRE( opt_A->has_moved ); // NOLINT(clang-analyzer-cplusplus.Move)
}
}
TEST_CASE( "Decomposer checks that the argument is 0 when handling " TEST_CASE( "Decomposer checks that the argument is 0 when handling "
"only-0-comparable types", "only-0-comparable types",
"[decomposition][approvals]" ) { "[decomposition][approvals]" ) {

View File

@@ -12,14 +12,13 @@
TEST_CASE("Parse uints", "[parse-numbers]") { TEST_CASE("Parse uints", "[parse-numbers]") {
using Catch::parseUInt; using Catch::parseUInt;
using Catch::Optional;
SECTION("proper inputs") { SECTION("proper inputs") {
REQUIRE( parseUInt( "0" ) == Optional<unsigned int>{ 0 } ); REQUIRE( parseUInt( "0" ) == std::optional<unsigned int>{ 0 } );
REQUIRE( parseUInt( "100" ) == Optional<unsigned int>{ 100 } ); REQUIRE( parseUInt( "100" ) == std::optional<unsigned int>{ 100 } );
REQUIRE( parseUInt( "4294967295" ) == REQUIRE( parseUInt( "4294967295" ) ==
Optional<unsigned int>{ 4294967295 } ); std::optional<unsigned int>{ 4294967295 } );
REQUIRE( parseUInt( "0xFF", 16 ) == Optional<unsigned int>{ 255 } ); REQUIRE( parseUInt( "0xFF", 16 ) == std::optional<unsigned int>{ 255 } );
} }
SECTION( "Bad inputs" ) { SECTION( "Bad inputs" ) {
// empty // empty