diff options
| author | Martin Hořeňovský | 2023-12-31 15:15:04 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2023-12-31 15:15:04 +0100 |
| commit | f981c9cbcac07a2690e5a86767eba490b5465463 (patch) | |
| tree | 3805b1a44240b2f1db71f73c54feed32ca11fc6c | |
| parent | b7b71ffd3a2a659412357964e91ee7db954e28df (diff) | |
| download | catch3-f981c9cbcac07a2690e5a86767eba490b5465463.tar.gz | |
v3.5.1v3.5.1
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | docs/release-notes.md | 12 | ||||
| -rw-r--r-- | extras/catch_amalgamated.cpp | 171 | ||||
| -rw-r--r-- | extras/catch_amalgamated.hpp | 476 | ||||
| -rw-r--r-- | meson.build | 2 | ||||
| -rw-r--r-- | src/catch2/catch_version.cpp | 2 | ||||
| -rw-r--r-- | src/catch2/catch_version_macros.hpp | 2 |
7 files changed, 383 insertions, 284 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 20e4036e..b4dd2b52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif() project(Catch2 - VERSION 3.5.0 # CML version placeholder, don't delete + VERSION 3.5.1 # CML version placeholder, don't delete LANGUAGES CXX # HOMEPAGE_URL is not supported until CMake version 3.12, which # we do not target yet. diff --git a/docs/release-notes.md b/docs/release-notes.md index 9751f2ce..0449ed0e 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,7 @@ # Release notes **Contents**<br> +[3.5.1](#351)<br> [3.5.0](#350)<br> [3.4.0](#340)<br> [3.3.2](#332)<br> @@ -58,6 +59,17 @@ [Even Older versions](#even-older-versions)<br> +## 3.5.1 + +### Improvements +* Significantly improved performance of the CLI parsing. + * This includes the cost of preparing the CLI parser, so Catch2's binaries start much faster. + +### Miscellaneous +* Added support for Bazel modules (#2781) +* Added CMake option to disable the build reproducibility settings (#2785) +* Added `log` library linking to the Meson build (#2784) + ## 3.5.0 diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp index cfc38a46..30e2d9f2 100644 --- a/extras/catch_amalgamated.cpp +++ b/extras/catch_amalgamated.cpp @@ -6,8 +6,8 @@ // SPDX-License-Identifier: BSL-1.0 -// Catch v3.5.0 -// Generated: 2023-12-11 00:51:07.662625 +// Catch v3.5.1 +// Generated: 2023-12-31 15:10:55.864983 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. @@ -2273,7 +2273,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 3, 5, 0, "", 0 ); + static Version version( 3, 5, 1, "", 0 ); return version; } @@ -2415,9 +2415,7 @@ namespace Catch { -#include <algorithm> #include <cassert> -#include <iomanip> namespace Catch { @@ -2627,13 +2625,29 @@ namespace { ; } - std::string normaliseOpt( std::string const& optName ) { -#ifdef CATCH_PLATFORM_WINDOWS - if ( optName[0] == '/' ) - return "-" + optName.substr( 1 ); - else + Catch::StringRef normaliseOpt( Catch::StringRef optName ) { + if ( optName[0] == '-' +#if defined(CATCH_PLATFORM_WINDOWS) + || optName[0] == '/' #endif - return optName; + ) { + return optName.substr( 1, optName.size() ); + } + + return optName; + } + + static size_t find_first_separator(Catch::StringRef sr) { + auto is_separator = []( char c ) { + return c == ' ' || c == ':' || c == '='; + }; + size_t pos = 0; + while (pos < sr.size()) { + if (is_separator(sr[pos])) { return pos; } + ++pos; + } + + return Catch::StringRef::npos; } } // namespace @@ -2651,23 +2665,23 @@ namespace Catch { } if ( it != itEnd ) { - auto const& next = *it; + StringRef next = *it; if ( isOptPrefix( next[0] ) ) { - auto delimiterPos = next.find_first_of( " :=" ); - if ( delimiterPos != std::string::npos ) { + auto delimiterPos = find_first_separator(next); + if ( delimiterPos != StringRef::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); m_tokenBuffer.push_back( { TokenType::Argument, - next.substr( delimiterPos + 1 ) } ); + next.substr( delimiterPos + 1, next.size() ) } ); } else { if ( next[1] != '-' && next.size() > 2 ) { - std::string opt = "- "; + // Combined short args, e.g. "-ab" for "-a -b" for ( size_t i = 1; i < next.size(); ++i ) { - opt[1] = next[i]; m_tokenBuffer.push_back( - { TokenType::Option, opt } ); + { TokenType::Option, + next.substr( i, 1 ) } ); } } else { m_tokenBuffer.push_back( @@ -2727,12 +2741,12 @@ namespace Catch { size_t ParserBase::cardinality() const { return 1; } InternalParseResult ParserBase::parse( Args const& args ) const { - return parse( args.exeName(), TokenStream( args ) ); + return parse( static_cast<std::string>(args.exeName()), TokenStream( args ) ); } ParseState::ParseState( ParseResultType type, - TokenStream const& remainingTokens ): - m_type( type ), m_remainingTokens( remainingTokens ) {} + TokenStream remainingTokens ): + m_type( type ), m_remainingTokens( CATCH_MOVE(remainingTokens) ) {} ParserResult BoundFlagRef::setFlag( bool flag ) { m_ref = flag; @@ -2750,34 +2764,34 @@ namespace Catch { } // namespace Detail Detail::InternalParseResult Arg::parse(std::string const&, - Detail::TokenStream const& tokens) const { + Detail::TokenStream tokens) const { auto validationResult = validate(); if (!validationResult) return Detail::InternalParseResult(validationResult); - auto remainingTokens = tokens; - auto const& token = *remainingTokens; + auto token = *tokens; if (token.type != Detail::TokenType::Argument) return Detail::InternalParseResult::ok(Detail::ParseState( - ParseResultType::NoMatch, remainingTokens)); + ParseResultType::NoMatch, CATCH_MOVE(tokens))); assert(!m_ref->isFlag()); auto valueRef = static_cast<Detail::BoundValueRefBase*>(m_ref.get()); - auto result = valueRef->setValue(remainingTokens->token); - if (!result) - return Detail::InternalParseResult(result); + auto result = valueRef->setValue(static_cast<std::string>(token.token)); + if ( !result ) + return Detail::InternalParseResult( result ); else - return Detail::InternalParseResult::ok(Detail::ParseState( - ParseResultType::Matched, ++remainingTokens)); + return Detail::InternalParseResult::ok( + Detail::ParseState( ParseResultType::Matched, + CATCH_MOVE( ++tokens ) ) ); } Opt::Opt(bool& ref) : ParserRefImpl(std::make_shared<Detail::BoundFlagRef>(ref)) {} - std::vector<Detail::HelpColumns> Opt::getHelpColumns() const { - std::ostringstream oss; + Detail::HelpColumns Opt::getHelpColumns() const { + ReusableStringStream oss; bool first = true; for (auto const& opt : m_optNames) { if (first) @@ -2788,10 +2802,10 @@ namespace Catch { } if (!m_hint.empty()) oss << " <" << m_hint << '>'; - return { { oss.str(), m_description } }; + return { oss.str(), m_description }; } - bool Opt::isMatch(std::string const& optToken) const { + bool Opt::isMatch(StringRef optToken) const { auto normalisedToken = normaliseOpt(optToken); for (auto const& name : m_optNames) { if (normaliseOpt(name) == normalisedToken) @@ -2801,15 +2815,14 @@ namespace Catch { } Detail::InternalParseResult Opt::parse(std::string const&, - Detail::TokenStream const& tokens) const { + Detail::TokenStream tokens) const { auto validationResult = validate(); if (!validationResult) return Detail::InternalParseResult(validationResult); - auto remainingTokens = tokens; - if (remainingTokens && - remainingTokens->type == Detail::TokenType::Option) { - auto const& token = *remainingTokens; + if (tokens && + tokens->type == Detail::TokenType::Option) { + auto const& token = *tokens; if (isMatch(token.token)) { if (m_ref->isFlag()) { auto flagRef = @@ -2821,35 +2834,35 @@ namespace Catch { if (result.value() == ParseResultType::ShortCircuitAll) return Detail::InternalParseResult::ok(Detail::ParseState( - result.value(), remainingTokens)); + result.value(), CATCH_MOVE(tokens))); } else { auto valueRef = static_cast<Detail::BoundValueRefBase*>( m_ref.get()); - ++remainingTokens; - if (!remainingTokens) + ++tokens; + if (!tokens) return Detail::InternalParseResult::runtimeError( "Expected argument following " + token.token); - auto const& argToken = *remainingTokens; + auto const& argToken = *tokens; if (argToken.type != Detail::TokenType::Argument) return Detail::InternalParseResult::runtimeError( "Expected argument following " + token.token); - const auto result = valueRef->setValue(argToken.token); + const auto result = valueRef->setValue(static_cast<std::string>(argToken.token)); if (!result) return Detail::InternalParseResult(result); if (result.value() == ParseResultType::ShortCircuitAll) return Detail::InternalParseResult::ok(Detail::ParseState( - result.value(), remainingTokens)); + result.value(), CATCH_MOVE(tokens))); } return Detail::InternalParseResult::ok(Detail::ParseState( - ParseResultType::Matched, ++remainingTokens)); + ParseResultType::Matched, CATCH_MOVE(++tokens))); } } return Detail::InternalParseResult::ok( - Detail::ParseState(ParseResultType::NoMatch, remainingTokens)); + Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens))); } Detail::Result Opt::validate() const { @@ -2881,9 +2894,9 @@ namespace Catch { Detail::InternalParseResult ExeName::parse(std::string const&, - Detail::TokenStream const& tokens) const { + Detail::TokenStream tokens) const { return Detail::InternalParseResult::ok( - Detail::ParseState(ParseResultType::NoMatch, tokens)); + Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens))); } ParserResult ExeName::set(std::string const& newName) { @@ -2913,9 +2926,9 @@ namespace Catch { std::vector<Detail::HelpColumns> Parser::getHelpColumns() const { std::vector<Detail::HelpColumns> cols; + cols.reserve( m_options.size() ); for ( auto const& o : m_options ) { - auto childCols = o.getHelpColumns(); - cols.insert( cols.end(), childCols.begin(), childCols.end() ); + cols.push_back(o.getHelpColumns()); } return cols; } @@ -2953,12 +2966,12 @@ namespace Catch { optWidth = ( std::min )( optWidth, consoleWidth / 2 ); - for ( auto const& cols : rows ) { - auto row = TextFlow::Column( cols.left ) + for ( auto& cols : rows ) { + auto row = TextFlow::Column( CATCH_MOVE(cols.left) ) .width( optWidth ) .indent( 2 ) + TextFlow::Spacer( 4 ) + - TextFlow::Column( cols.right ) + TextFlow::Column( static_cast<std::string>(cols.descriptions) ) .width( consoleWidth - 7 - optWidth ); os << row << '\n'; } @@ -2980,7 +2993,7 @@ namespace Catch { Detail::InternalParseResult Parser::parse( std::string const& exeName, - Detail::TokenStream const& tokens ) const { + Detail::TokenStream tokens ) const { struct ParserInfo { ParserBase const* parser = nullptr; @@ -2998,7 +3011,7 @@ namespace Catch { m_exeName.set( exeName ); auto result = Detail::InternalParseResult::ok( - Detail::ParseState( ParseResultType::NoMatch, tokens ) ); + Detail::ParseState( ParseResultType::NoMatch, CATCH_MOVE(tokens) ) ); while ( result.value().remainingTokens() ) { bool tokenParsed = false; @@ -3006,7 +3019,7 @@ namespace Catch { if ( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { result = parseInfo.parser->parse( - exeName, result.value().remainingTokens() ); + exeName, CATCH_MOVE(result).value().remainingTokens() ); if ( !result ) return result; if ( result.value().type() != @@ -3032,7 +3045,7 @@ namespace Catch { Args::Args(int argc, char const* const* argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {} - Args::Args(std::initializer_list<std::string> args) : + Args::Args(std::initializer_list<StringRef> args) : m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {} @@ -3338,8 +3351,8 @@ namespace Catch { ( "split the tests to execute into this many groups" ) | Opt( setShardIndex, "shard index" ) ["--shard-index"] - ( "index of the group of tests to execute (see --shard-count)" ) | - Opt( config.allowZeroTests ) + ( "index of the group of tests to execute (see --shard-count)" ) + | Opt( config.allowZeroTests ) ["--allow-running-no-tests"] ( "Treat 'No tests run' as a success" ) | Arg( config.testsOrTags, "test name|pattern|tags" ) @@ -4641,7 +4654,6 @@ Catch::LeakDetector::~LeakDetector() { - namespace Catch { namespace { @@ -6527,7 +6539,6 @@ namespace Catch { return sorted; } case TestRunOrder::Randomized: { - seedRng(config); using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>; TestCaseInfoHasher h{ config.rngSeed() }; @@ -7390,23 +7401,36 @@ namespace Catch { return os; } - Columns Column::operator+( Column const& other ) { + Columns operator+(Column const& lhs, Column const& rhs) { Columns cols; - cols += *this; - cols += other; + cols += lhs; + cols += rhs; return cols; } - - Columns& Columns::operator+=( Column const& col ) { - m_columns.push_back( col ); - return *this; + Columns operator+(Column&& lhs, Column&& rhs) { + Columns cols; + cols += CATCH_MOVE( lhs ); + cols += CATCH_MOVE( rhs ); + return cols; } - Columns Columns::operator+( Column const& col ) { - Columns combined = *this; - combined += col; + Columns& operator+=(Columns& lhs, Column const& rhs) { + lhs.m_columns.push_back( rhs ); + return lhs; + } + Columns& operator+=(Columns& lhs, Column&& rhs) { + lhs.m_columns.push_back( CATCH_MOVE(rhs) ); + return lhs; + } + Columns operator+( Columns const& lhs, Column const& rhs ) { + auto combined( lhs ); + combined += rhs; return combined; } + Columns operator+( Columns&& lhs, Column&& rhs ) { + lhs += CATCH_MOVE( rhs ); + return CATCH_MOVE( lhs ); + } } // namespace TextFlow } // namespace Catch @@ -8881,11 +8905,10 @@ public: *this << RowBreak(); TextFlow::Columns headerCols; - auto spacer = TextFlow::Spacer(2); for (auto const& info : m_columnInfos) { assert(info.width > 2); headerCols += TextFlow::Column(info.name).width(info.width - 2); - headerCols += spacer; + headerCols += TextFlow::Spacer( 2 ); } m_os << headerCols << '\n'; diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp index bec588d4..4f075857 100644 --- a/extras/catch_amalgamated.hpp +++ b/extras/catch_amalgamated.hpp @@ -6,8 +6,8 @@ // SPDX-License-Identifier: BSL-1.0 -// Catch v3.5.0 -// Generated: 2023-12-11 00:51:06.770598 +// Catch v3.5.1 +// Generated: 2023-12-31 15:10:53.044176 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. @@ -690,6 +690,8 @@ namespace Catch { using size_type = std::size_t; using const_iterator = const char*; + static constexpr size_type npos{ static_cast<size_type>( -1 ) }; + private: static constexpr char const* const s_empty = ""; @@ -740,7 +742,7 @@ namespace Catch { } // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, start + size()). + // If start + length > size(), then the substring is [start, size()). // If start > size(), then the substring is empty. constexpr StringRef substr(size_type start, size_type length) const noexcept { if (start < m_size) { @@ -1969,12 +1971,12 @@ namespace Catch { template <typename Clock> int warmup() { - return run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(warmup_time), warmup_seed, &resolution<Clock>) + return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>) .iterations; } template <typename Clock> EnvironmentEstimate estimate_clock_resolution(int iterations) { - auto r = run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(clock_resolution_estimation_time), iterations, &resolution<Clock>) + auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>) .result; return { FDuration(mean(r.data(), r.data() + r.size())), @@ -1996,7 +1998,7 @@ namespace Catch { }; time_clock(1); int iters = clock_cost_estimation_iterations; - auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(clock_cost_estimation_time), iters, time_clock); + auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock); std::vector<double> times; int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed)); times.reserve(static_cast<size_t>(nsamples)); @@ -3639,141 +3641,6 @@ namespace Catch { #define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED - -#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED -#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED - - -#include <iosfwd> -#include <cstdint> - -namespace Catch { - - enum class ColourMode : std::uint8_t; - class IStream; - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - BrightYellow = Bright | Yellow, - - // By intention - FileName = LightGrey, - Warning = BrightYellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - Skip = LightGrey, - - OriginalExpression = Cyan, - ReconstructedExpression = BrightYellow, - - SecondaryText = LightGrey, - Headers = White - }; - }; - - class ColourImpl { - protected: - //! The associated stream of this ColourImpl instance - IStream* m_stream; - public: - ColourImpl( IStream* stream ): m_stream( stream ) {} - - //! RAII wrapper around writing specific colour of text using specific - //! colour impl into a stream. - class ColourGuard { - ColourImpl const* m_colourImpl; - Colour::Code m_code; - bool m_engaged = false; - - public: - //! Does **not** engage the guard/start the colour - ColourGuard( Colour::Code code, - ColourImpl const* colour ); - - ColourGuard( ColourGuard const& rhs ) = delete; - ColourGuard& operator=( ColourGuard const& rhs ) = delete; - - ColourGuard( ColourGuard&& rhs ) noexcept; - ColourGuard& operator=( ColourGuard&& rhs ) noexcept; - - //! Removes colour _if_ the guard was engaged - ~ColourGuard(); - - /** - * Explicitly engages colour for given stream. - * - * The API based on operator<< should be preferred. - */ - ColourGuard& engage( std::ostream& stream ) &; - /** - * Explicitly engages colour for given stream. - * - * The API based on operator<< should be preferred. - */ - ColourGuard&& engage( std::ostream& stream ) &&; - - private: - //! Engages the guard and starts using colour - friend std::ostream& operator<<( std::ostream& lhs, - ColourGuard& guard ) { - guard.engageImpl( lhs ); - return lhs; - } - //! Engages the guard and starts using colour - friend std::ostream& operator<<( std::ostream& lhs, - ColourGuard&& guard) { - guard.engageImpl( lhs ); - return lhs; - } - - void engageImpl( std::ostream& stream ); - - }; - - virtual ~ColourImpl(); // = default - /** - * Creates a guard object for given colour and this colour impl - * - * **Important:** - * the guard starts disengaged, and has to be engaged explicitly. - */ - ColourGuard guardColour( Colour::Code colourCode ); - - private: - virtual void use( Colour::Code colourCode ) const = 0; - }; - - //! Provides ColourImpl based on global config and target compilation platform - Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection, - IStream* stream ); - - //! Checks if specific colour impl has been compiled into the binary - bool isColourImplAvailable( ColourMode colourSelection ); - -} // end namespace Catch - -#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED - #include <map> #include <string> #include <vector> @@ -4387,17 +4254,16 @@ namespace Catch { enum class TokenType { Option, Argument }; struct Token { TokenType type; - std::string token; + StringRef token; }; // Abstracts iterators into args as a stream of tokens, with option // arguments uniformly handled class TokenStream { - using Iterator = std::vector<std::string>::const_iterator; + using Iterator = std::vector<StringRef>::const_iterator; Iterator it; Iterator itEnd; std::vector<Token> m_tokenBuffer; - void loadBuffer(); public: @@ -4449,12 +4315,17 @@ namespace Catch { ResultType m_type; }; - template <typename T> class ResultValueBase : public ResultBase { + template <typename T> + class ResultValueBase : public ResultBase { public: - auto value() const -> T const& { + T const& value() const& { enforceOk(); return m_value; } + T&& value() && { + enforceOk(); + return CATCH_MOVE( m_value ); + } protected: ResultValueBase( ResultType type ): ResultBase( type ) {} @@ -4464,13 +4335,23 @@ namespace Catch { if ( m_type == ResultType::Ok ) new ( &m_value ) T( other.m_value ); } + ResultValueBase( ResultValueBase&& other ): + ResultBase( other ) { + if ( m_type == ResultType::Ok ) + new ( &m_value ) T( CATCH_MOVE(other.m_value) ); + } + - ResultValueBase( ResultType, T const& value ): ResultBase( ResultType::Ok ) { + ResultValueBase( ResultType, T const& value ): + ResultBase( ResultType::Ok ) { new ( &m_value ) T( value ); } + ResultValueBase( ResultType, T&& value ): + ResultBase( ResultType::Ok ) { + new ( &m_value ) T( CATCH_MOVE(value) ); + } - auto operator=( ResultValueBase const& other ) - -> ResultValueBase& { + ResultValueBase& operator=( ResultValueBase const& other ) { if ( m_type == ResultType::Ok ) m_value.~T(); ResultBase::operator=( other ); @@ -4478,6 +4359,14 @@ namespace Catch { new ( &m_value ) T( other.m_value ); return *this; } + ResultValueBase& operator=( ResultValueBase&& other ) { + if ( m_type == ResultType::Ok ) m_value.~T(); + ResultBase::operator=( other ); + if ( m_type == ResultType::Ok ) + new ( &m_value ) T( CATCH_MOVE(other.m_value) ); + return *this; + } + ~ResultValueBase() override { if ( m_type == ResultType::Ok ) @@ -4505,8 +4394,8 @@ namespace Catch { } template <typename U> - static auto ok( U const& value ) -> BasicResult { - return { ResultType::Ok, value }; + static auto ok( U&& value ) -> BasicResult { + return { ResultType::Ok, CATCH_FORWARD(value) }; } static auto ok() -> BasicResult { return { ResultType::Ok }; } static auto logicError( std::string&& message ) @@ -4553,12 +4442,15 @@ namespace Catch { class ParseState { public: ParseState( ParseResultType type, - TokenStream const& remainingTokens ); + TokenStream remainingTokens ); ParseResultType type() const { return m_type; } - TokenStream const& remainingTokens() const { + TokenStream const& remainingTokens() const& { return m_remainingTokens; } + TokenStream&& remainingTokens() && { + return CATCH_MOVE( m_remainingTokens ); + } private: ParseResultType m_type; @@ -4571,7 +4463,7 @@ namespace Catch { struct HelpColumns { std::string left; - std::string right; + StringRef descriptions; }; template <typename T> @@ -4731,7 +4623,7 @@ namespace Catch { virtual ~ParserBase() = default; virtual auto validate() const -> Result { return Result::ok(); } virtual auto parse( std::string const& exeName, - TokenStream const& tokens ) const + TokenStream tokens ) const -> InternalParseResult = 0; virtual size_t cardinality() const; @@ -4751,8 +4643,8 @@ namespace Catch { protected: Optionality m_optionality = Optionality::Optional; std::shared_ptr<BoundRef> m_ref; - std::string m_hint; - std::string m_description; + StringRef m_hint; + StringRef m_description; explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ): m_ref( ref ) {} @@ -4761,28 +4653,32 @@ namespace Catch { template <typename LambdaT> ParserRefImpl( accept_many_t, LambdaT const& ref, - std::string const& hint ): + StringRef hint ): m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ), m_hint( hint ) {} template <typename T, typename = typename std::enable_if_t< !Detail::is_unary_function<T>::value>> - ParserRefImpl( T& ref, std::string const& hint ): + ParserRefImpl( T& ref, StringRef hint ): m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), m_hint( hint ) {} template <typename LambdaT, typename = typename std::enable_if_t< Detail::is_unary_function<LambdaT>::value>> - ParserRefImpl( LambdaT const& ref, std::string const& hint ): + ParserRefImpl( LambdaT const& ref, StringRef hint ): m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), m_hint( hint ) {} - auto operator()( std::string const& description ) -> DerivedT& { + DerivedT& operator()( StringRef description ) & { m_description = description; return static_cast<DerivedT&>( *this ); } + DerivedT&& operator()( StringRef description ) && { + m_description = description; + return static_cast<DerivedT&&>( *this ); + } auto optional() -> DerivedT& { m_optionality = Optionality::Optional; @@ -4805,7 +4701,7 @@ namespace Catch { return 1; } - std::string const& hint() const { return m_hint; } + StringRef hint() const { return m_hint; } }; } // namespace detail @@ -4819,13 +4715,13 @@ namespace |