Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:08:50

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
0008 #ifndef CATCH_CLARA_HPP_INCLUDED
0009 #define CATCH_CLARA_HPP_INCLUDED
0010 
0011 #if defined( __clang__ )
0012 #    pragma clang diagnostic push
0013 #    pragma clang diagnostic ignored "-Wweak-vtables"
0014 #    pragma clang diagnostic ignored "-Wshadow"
0015 #    pragma clang diagnostic ignored "-Wdeprecated"
0016 #endif
0017 
0018 #if defined( __GNUC__ )
0019 #    pragma GCC diagnostic push
0020 #    pragma GCC diagnostic ignored "-Wsign-conversion"
0021 #endif
0022 
0023 #ifndef CLARA_CONFIG_OPTIONAL_TYPE
0024 #    ifdef __has_include
0025 #        if __has_include( <optional>) && __cplusplus >= 201703L
0026 #            include <optional>
0027 #            define CLARA_CONFIG_OPTIONAL_TYPE std::optional
0028 #        endif
0029 #    endif
0030 #endif
0031 
0032 #include <catch2/internal/catch_stringref.hpp>
0033 #include <catch2/internal/catch_move_and_forward.hpp>
0034 #include <catch2/internal/catch_noncopyable.hpp>
0035 #include <catch2/internal/catch_void_type.hpp>
0036 
0037 #include <cassert>
0038 #include <memory>
0039 #include <ostream>
0040 #include <sstream>
0041 #include <string>
0042 #include <type_traits>
0043 #include <vector>
0044 
0045 namespace Catch {
0046     namespace Clara {
0047 
0048         class Args;
0049         class Parser;
0050 
0051         // enum of result types from a parse
0052         enum class ParseResultType {
0053             Matched,
0054             NoMatch,
0055             ShortCircuitAll,
0056             ShortCircuitSame
0057         };
0058 
0059         struct accept_many_t {};
0060         constexpr accept_many_t accept_many {};
0061 
0062         namespace Detail {
0063             struct fake_arg {
0064                 template <typename T>
0065                 operator T();
0066             };
0067 
0068             template <typename F, typename = void>
0069             struct is_unary_function : std::false_type {};
0070 
0071             template <typename F>
0072             struct is_unary_function<
0073                 F,
0074                 Catch::Detail::void_t<decltype(
0075                     std::declval<F>()( fake_arg() ) )
0076                 >
0077             > : std::true_type {};
0078 
0079             // Traits for extracting arg and return type of lambdas (for single
0080             // argument lambdas)
0081             template <typename L>
0082             struct UnaryLambdaTraits
0083                 : UnaryLambdaTraits<decltype( &L::operator() )> {};
0084 
0085             template <typename ClassT, typename ReturnT, typename... Args>
0086             struct UnaryLambdaTraits<ReturnT ( ClassT::* )( Args... ) const> {
0087                 static const bool isValid = false;
0088             };
0089 
0090             template <typename ClassT, typename ReturnT, typename ArgT>
0091             struct UnaryLambdaTraits<ReturnT ( ClassT::* )( ArgT ) const> {
0092                 static const bool isValid = true;
0093                 using ArgType = std::remove_const_t<std::remove_reference_t<ArgT>>;
0094                 using ReturnType = ReturnT;
0095             };
0096 
0097             class TokenStream;
0098 
0099             // Wraps a token coming from a token stream. These may not directly
0100             // correspond to strings as a single string may encode an option +
0101             // its argument if the : or = form is used
0102             enum class TokenType { Option, Argument };
0103             struct Token {
0104                 TokenType type;
0105                 StringRef token;
0106             };
0107 
0108             // Abstracts iterators into args as a stream of tokens, with option
0109             // arguments uniformly handled
0110             class TokenStream {
0111                 using Iterator = std::vector<StringRef>::const_iterator;
0112                 Iterator it;
0113                 Iterator itEnd;
0114                 std::vector<Token> m_tokenBuffer;
0115                 void loadBuffer();
0116 
0117             public:
0118                 explicit TokenStream( Args const& args );
0119                 TokenStream( Iterator it, Iterator itEnd );
0120 
0121                 explicit operator bool() const {
0122                     return !m_tokenBuffer.empty() || it != itEnd;
0123                 }
0124 
0125                 size_t count() const {
0126                     return m_tokenBuffer.size() + ( itEnd - it );
0127                 }
0128 
0129                 Token operator*() const {
0130                     assert( !m_tokenBuffer.empty() );
0131                     return m_tokenBuffer.front();
0132                 }
0133 
0134                 Token const* operator->() const {
0135                     assert( !m_tokenBuffer.empty() );
0136                     return &m_tokenBuffer.front();
0137                 }
0138 
0139                 TokenStream& operator++();
0140             };
0141 
0142             //! Denotes type of a parsing result
0143             enum class ResultType {
0144                 Ok,          ///< No errors
0145                 LogicError,  ///< Error in user-specified arguments for
0146                              ///< construction
0147                 RuntimeError ///< Error in parsing inputs
0148             };
0149 
0150             class ResultBase {
0151             protected:
0152                 ResultBase( ResultType type ): m_type( type ) {}
0153                 virtual ~ResultBase(); // = default;
0154 
0155 
0156                 ResultBase(ResultBase const&) = default;
0157                 ResultBase& operator=(ResultBase const&) = default;
0158                 ResultBase(ResultBase&&) = default;
0159                 ResultBase& operator=(ResultBase&&) = default;
0160 
0161                 virtual void enforceOk() const = 0;
0162 
0163                 ResultType m_type;
0164             };
0165 
0166             template <typename T>
0167             class ResultValueBase : public ResultBase {
0168             public:
0169                 T const& value() const& {
0170                     enforceOk();
0171                     return m_value;
0172                 }
0173                 T&& value() && {
0174                     enforceOk();
0175                     return CATCH_MOVE( m_value );
0176                 }
0177 
0178             protected:
0179                 ResultValueBase( ResultType type ): ResultBase( type ) {}
0180 
0181                 ResultValueBase( ResultValueBase const& other ):
0182                     ResultBase( other ) {
0183                     if ( m_type == ResultType::Ok )
0184                         new ( &m_value ) T( other.m_value );
0185                 }
0186                 ResultValueBase( ResultValueBase&& other ):
0187                     ResultBase( other ) {
0188                     if ( m_type == ResultType::Ok )
0189                         new ( &m_value ) T( CATCH_MOVE(other.m_value) );
0190                 }
0191 
0192 
0193                 ResultValueBase( ResultType, T const& value ):
0194                     ResultBase( ResultType::Ok ) {
0195                     new ( &m_value ) T( value );
0196                 }
0197                 ResultValueBase( ResultType, T&& value ):
0198                     ResultBase( ResultType::Ok ) {
0199                     new ( &m_value ) T( CATCH_MOVE(value) );
0200                 }
0201 
0202                 ResultValueBase& operator=( ResultValueBase const& other ) {
0203                     if ( m_type == ResultType::Ok )
0204                         m_value.~T();
0205                     ResultBase::operator=( other );
0206                     if ( m_type == ResultType::Ok )
0207                         new ( &m_value ) T( other.m_value );
0208                     return *this;
0209                 }
0210                 ResultValueBase& operator=( ResultValueBase&& other ) {
0211                     if ( m_type == ResultType::Ok ) m_value.~T();
0212                     ResultBase::operator=( other );
0213                     if ( m_type == ResultType::Ok )
0214                         new ( &m_value ) T( CATCH_MOVE(other.m_value) );
0215                     return *this;
0216                 }
0217 
0218 
0219                 ~ResultValueBase() override {
0220                     if ( m_type == ResultType::Ok )
0221                         m_value.~T();
0222                 }
0223 
0224                 union {
0225                     T m_value;
0226                 };
0227             };
0228 
0229             template <> class ResultValueBase<void> : public ResultBase {
0230             protected:
0231                 using ResultBase::ResultBase;
0232             };
0233 
0234             template <typename T = void>
0235             class BasicResult : public ResultValueBase<T> {
0236             public:
0237                 template <typename U>
0238                 explicit BasicResult( BasicResult<U> const& other ):
0239                     ResultValueBase<T>( other.type() ),
0240                     m_errorMessage( other.errorMessage() ) {
0241                     assert( type() != ResultType::Ok );
0242                 }
0243 
0244                 template <typename U>
0245                 static auto ok( U&& value ) -> BasicResult {
0246                     return { ResultType::Ok, CATCH_FORWARD(value) };
0247                 }
0248                 static auto ok() -> BasicResult { return { ResultType::Ok }; }
0249                 static auto logicError( std::string&& message )
0250                     -> BasicResult {
0251                     return { ResultType::LogicError, CATCH_MOVE(message) };
0252                 }
0253                 static auto runtimeError( std::string&& message )
0254                     -> BasicResult {
0255                     return { ResultType::RuntimeError, CATCH_MOVE(message) };
0256                 }
0257 
0258                 explicit operator bool() const {
0259                     return m_type == ResultType::Ok;
0260                 }
0261                 auto type() const -> ResultType { return m_type; }
0262                 auto errorMessage() const -> std::string const& {
0263                     return m_errorMessage;
0264                 }
0265 
0266             protected:
0267                 void enforceOk() const override {
0268 
0269                     // Errors shouldn't reach this point, but if they do
0270                     // the actual error message will be in m_errorMessage
0271                     assert( m_type != ResultType::LogicError );
0272                     assert( m_type != ResultType::RuntimeError );
0273                     if ( m_type != ResultType::Ok )
0274                         std::abort();
0275                 }
0276 
0277                 std::string
0278                     m_errorMessage; // Only populated if resultType is an error
0279 
0280                 BasicResult( ResultType type,
0281                              std::string&& message ):
0282                     ResultValueBase<T>( type ), m_errorMessage( CATCH_MOVE(message) ) {
0283                     assert( m_type != ResultType::Ok );
0284                 }
0285 
0286                 using ResultValueBase<T>::ResultValueBase;
0287                 using ResultBase::m_type;
0288             };
0289 
0290             class ParseState {
0291             public:
0292                 ParseState( ParseResultType type,
0293                             TokenStream remainingTokens );
0294 
0295                 ParseResultType type() const { return m_type; }
0296                 TokenStream const& remainingTokens() const& {
0297                     return m_remainingTokens;
0298                 }
0299                 TokenStream&& remainingTokens() && {
0300                     return CATCH_MOVE( m_remainingTokens );
0301                 }
0302 
0303             private:
0304                 ParseResultType m_type;
0305                 TokenStream m_remainingTokens;
0306             };
0307 
0308             using Result = BasicResult<void>;
0309             using ParserResult = BasicResult<ParseResultType>;
0310             using InternalParseResult = BasicResult<ParseState>;
0311 
0312             struct HelpColumns {
0313                 std::string left;
0314                 StringRef descriptions;
0315             };
0316 
0317             template <typename T>
0318             ParserResult convertInto( std::string const& source, T& target ) {
0319                 std::stringstream ss( source );
0320                 ss >> target;
0321                 if ( ss.fail() ) {
0322                     return ParserResult::runtimeError(
0323                         "Unable to convert '" + source +
0324                         "' to destination type" );
0325                 } else {
0326                     return ParserResult::ok( ParseResultType::Matched );
0327                 }
0328             }
0329             ParserResult convertInto( std::string const& source,
0330                                       std::string& target );
0331             ParserResult convertInto( std::string const& source, bool& target );
0332 
0333 #ifdef CLARA_CONFIG_OPTIONAL_TYPE
0334             template <typename T>
0335             auto convertInto( std::string const& source,
0336                               CLARA_CONFIG_OPTIONAL_TYPE<T>& target )
0337                 -> ParserResult {
0338                 T temp;
0339                 auto result = convertInto( source, temp );
0340                 if ( result )
0341                     target = CATCH_MOVE( temp );
0342                 return result;
0343             }
0344 #endif // CLARA_CONFIG_OPTIONAL_TYPE
0345 
0346             struct BoundRef : Catch::Detail::NonCopyable {
0347                 virtual ~BoundRef() = default;
0348                 virtual bool isContainer() const;
0349                 virtual bool isFlag() const;
0350             };
0351             struct BoundValueRefBase : BoundRef {
0352                 virtual auto setValue( std::string const& arg )
0353                     -> ParserResult = 0;
0354             };
0355             struct BoundFlagRefBase : BoundRef {
0356                 virtual auto setFlag( bool flag ) -> ParserResult = 0;
0357                 bool isFlag() const override;
0358             };
0359 
0360             template <typename T> struct BoundValueRef : BoundValueRefBase {
0361                 T& m_ref;
0362 
0363                 explicit BoundValueRef( T& ref ): m_ref( ref ) {}
0364 
0365                 ParserResult setValue( std::string const& arg ) override {
0366                     return convertInto( arg, m_ref );
0367                 }
0368             };
0369 
0370             template <typename T>
0371             struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
0372                 std::vector<T>& m_ref;
0373 
0374                 explicit BoundValueRef( std::vector<T>& ref ): m_ref( ref ) {}
0375 
0376                 auto isContainer() const -> bool override { return true; }
0377 
0378                 auto setValue( std::string const& arg )
0379                     -> ParserResult override {
0380                     T temp;
0381                     auto result = convertInto( arg, temp );
0382                     if ( result )
0383                         m_ref.push_back( temp );
0384                     return result;
0385                 }
0386             };
0387 
0388             struct BoundFlagRef : BoundFlagRefBase {
0389                 bool& m_ref;
0390 
0391                 explicit BoundFlagRef( bool& ref ): m_ref( ref ) {}
0392 
0393                 ParserResult setFlag( bool flag ) override;
0394             };
0395 
0396             template <typename ReturnType> struct LambdaInvoker {
0397                 static_assert(
0398                     std::is_same<ReturnType, ParserResult>::value,
0399                     "Lambda must return void or clara::ParserResult" );
0400 
0401                 template <typename L, typename ArgType>
0402                 static auto invoke( L const& lambda, ArgType const& arg )
0403                     -> ParserResult {
0404                     return lambda( arg );
0405                 }
0406             };
0407 
0408             template <> struct LambdaInvoker<void> {
0409                 template <typename L, typename ArgType>
0410                 static auto invoke( L const& lambda, ArgType const& arg )
0411                     -> ParserResult {
0412                     lambda( arg );
0413                     return ParserResult::ok( ParseResultType::Matched );
0414                 }
0415             };
0416 
0417             template <typename ArgType, typename L>
0418             auto invokeLambda( L const& lambda, std::string const& arg )
0419                 -> ParserResult {
0420                 ArgType temp{};
0421                 auto result = convertInto( arg, temp );
0422                 return !result ? result
0423                                : LambdaInvoker<typename UnaryLambdaTraits<
0424                                      L>::ReturnType>::invoke( lambda, temp );
0425             }
0426 
0427             template <typename L> struct BoundLambda : BoundValueRefBase {
0428                 L m_lambda;
0429 
0430                 static_assert(
0431                     UnaryLambdaTraits<L>::isValid,
0432                     "Supplied lambda must take exactly one argument" );
0433                 explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {}
0434 
0435                 auto setValue( std::string const& arg )
0436                     -> ParserResult override {
0437                     return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(
0438                         m_lambda, arg );
0439                 }
0440             };
0441 
0442             template <typename L> struct BoundManyLambda : BoundLambda<L> {
0443                 explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {}
0444                 bool isContainer() const override { return true; }
0445             };
0446 
0447             template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
0448                 L m_lambda;
0449 
0450                 static_assert(
0451                     UnaryLambdaTraits<L>::isValid,
0452                     "Supplied lambda must take exactly one argument" );
0453                 static_assert(
0454                     std::is_same<typename UnaryLambdaTraits<L>::ArgType,
0455                                  bool>::value,
0456                     "flags must be boolean" );
0457 
0458                 explicit BoundFlagLambda( L const& lambda ):
0459                     m_lambda( lambda ) {}
0460 
0461                 auto setFlag( bool flag ) -> ParserResult override {
0462                     return LambdaInvoker<typename UnaryLambdaTraits<
0463                         L>::ReturnType>::invoke( m_lambda, flag );
0464                 }
0465             };
0466 
0467             enum class Optionality { Optional, Required };
0468 
0469             class ParserBase {
0470             public:
0471                 virtual ~ParserBase() = default;
0472                 virtual auto validate() const -> Result { return Result::ok(); }
0473                 virtual auto parse( std::string const& exeName,
0474                                     TokenStream tokens ) const
0475                     -> InternalParseResult = 0;
0476                 virtual size_t cardinality() const;
0477 
0478                 InternalParseResult parse( Args const& args ) const;
0479             };
0480 
0481             template <typename DerivedT>
0482             class ComposableParserImpl : public ParserBase {
0483             public:
0484                 template <typename T>
0485                 auto operator|( T const& other ) const -> Parser;
0486             };
0487 
0488             // Common code and state for Args and Opts
0489             template <typename DerivedT>
0490             class ParserRefImpl : public ComposableParserImpl<DerivedT> {
0491             protected:
0492                 Optionality m_optionality = Optionality::Optional;
0493                 std::shared_ptr<BoundRef> m_ref;
0494                 StringRef m_hint;
0495                 StringRef m_description;
0496 
0497                 explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
0498                     m_ref( ref ) {}
0499 
0500             public:
0501                 template <typename LambdaT>
0502                 ParserRefImpl( accept_many_t,
0503                                LambdaT const& ref,
0504                                StringRef hint ):
0505                     m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
0506                     m_hint( hint ) {}
0507 
0508                 template <typename T,
0509                           typename = typename std::enable_if_t<
0510                               !Detail::is_unary_function<T>::value>>
0511                 ParserRefImpl( T& ref, StringRef hint ):
0512                     m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
0513                     m_hint( hint ) {}
0514 
0515                 template <typename LambdaT,
0516                           typename = typename std::enable_if_t<
0517                               Detail::is_unary_function<LambdaT>::value>>
0518                 ParserRefImpl( LambdaT const& ref, StringRef hint ):
0519                     m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
0520                     m_hint( hint ) {}
0521 
0522                 DerivedT& operator()( StringRef description ) & {
0523                     m_description = description;
0524                     return static_cast<DerivedT&>( *this );
0525                 }
0526                 DerivedT&& operator()( StringRef description ) && {
0527                     m_description = description;
0528                     return static_cast<DerivedT&&>( *this );
0529                 }
0530 
0531                 auto optional() -> DerivedT& {
0532                     m_optionality = Optionality::Optional;
0533                     return static_cast<DerivedT&>( *this );
0534                 }
0535 
0536                 auto required() -> DerivedT& {
0537                     m_optionality = Optionality::Required;
0538                     return static_cast<DerivedT&>( *this );
0539                 }
0540 
0541                 auto isOptional() const -> bool {
0542                     return m_optionality == Optionality::Optional;
0543                 }
0544 
0545                 auto cardinality() const -> size_t override {
0546                     if ( m_ref->isContainer() )
0547                         return 0;
0548                     else
0549                         return 1;
0550                 }
0551 
0552                 StringRef hint() const { return m_hint; }
0553             };
0554 
0555         } // namespace detail
0556 
0557 
0558         // A parser for arguments
0559         class Arg : public Detail::ParserRefImpl<Arg> {
0560         public:
0561             using ParserRefImpl::ParserRefImpl;
0562             using ParserBase::parse;
0563 
0564             Detail::InternalParseResult
0565                 parse(std::string const&,
0566                       Detail::TokenStream tokens) const override;
0567         };
0568 
0569         // A parser for options
0570         class Opt : public Detail::ParserRefImpl<Opt> {
0571         protected:
0572             std::vector<StringRef> m_optNames;
0573 
0574         public:
0575             template <typename LambdaT>
0576             explicit Opt(LambdaT const& ref) :
0577                 ParserRefImpl(
0578                     std::make_shared<Detail::BoundFlagLambda<LambdaT>>(ref)) {}
0579 
0580             explicit Opt(bool& ref);
0581 
0582             template <typename LambdaT,
0583                       typename = typename std::enable_if_t<
0584                           Detail::is_unary_function<LambdaT>::value>>
0585             Opt( LambdaT const& ref, StringRef hint ):
0586                 ParserRefImpl( ref, hint ) {}
0587 
0588             template <typename LambdaT>
0589             Opt( accept_many_t, LambdaT const& ref, StringRef hint ):
0590                 ParserRefImpl( accept_many, ref, hint ) {}
0591 
0592             template <typename T,
0593                       typename = typename std::enable_if_t<
0594                           !Detail::is_unary_function<T>::value>>
0595             Opt( T& ref, StringRef hint ):
0596                 ParserRefImpl( ref, hint ) {}
0597 
0598             Opt& operator[]( StringRef optName ) & {
0599                 m_optNames.push_back(optName);
0600                 return *this;
0601             }
0602             Opt&& operator[]( StringRef optName ) && {
0603                 m_optNames.push_back( optName );
0604                 return CATCH_MOVE(*this);
0605             }
0606 
0607             Detail::HelpColumns getHelpColumns() const;
0608 
0609             bool isMatch(StringRef optToken) const;
0610 
0611             using ParserBase::parse;
0612 
0613             Detail::InternalParseResult
0614                 parse(std::string const&,
0615                       Detail::TokenStream tokens) const override;
0616 
0617             Detail::Result validate() const override;
0618         };
0619 
0620         // Specifies the name of the executable
0621         class ExeName : public Detail::ComposableParserImpl<ExeName> {
0622             std::shared_ptr<std::string> m_name;
0623             std::shared_ptr<Detail::BoundValueRefBase> m_ref;
0624 
0625         public:
0626             ExeName();
0627             explicit ExeName(std::string& ref);
0628 
0629             template <typename LambdaT>
0630             explicit ExeName(LambdaT const& lambda) : ExeName() {
0631                 m_ref = std::make_shared<Detail::BoundLambda<LambdaT>>(lambda);
0632             }
0633 
0634             // The exe name is not parsed out of the normal tokens, but is
0635             // handled specially
0636             Detail::InternalParseResult
0637                 parse(std::string const&,
0638                       Detail::TokenStream tokens) const override;
0639 
0640             std::string const& name() const { return *m_name; }
0641             Detail::ParserResult set(std::string const& newName);
0642         };
0643 
0644 
0645         // A Combined parser
0646         class Parser : Detail::ParserBase {
0647             mutable ExeName m_exeName;
0648             std::vector<Opt> m_options;
0649             std::vector<Arg> m_args;
0650 
0651         public:
0652 
0653             auto operator|=(ExeName const& exeName) -> Parser& {
0654                 m_exeName = exeName;
0655                 return *this;
0656             }
0657 
0658             auto operator|=(Arg const& arg) -> Parser& {
0659                 m_args.push_back(arg);
0660                 return *this;
0661             }
0662 
0663             friend Parser& operator|=( Parser& p, Opt const& opt ) {
0664                 p.m_options.push_back( opt );
0665                 return p;
0666             }
0667             friend Parser& operator|=( Parser& p, Opt&& opt ) {
0668                 p.m_options.push_back( CATCH_MOVE(opt) );
0669                 return p;
0670             }
0671 
0672             Parser& operator|=(Parser const& other);
0673 
0674             template <typename T>
0675             friend Parser operator|( Parser const& p, T&& rhs ) {
0676                 Parser temp( p );
0677                 temp |= rhs;
0678                 return temp;
0679             }
0680 
0681             template <typename T>
0682             friend Parser operator|( Parser&& p, T&& rhs ) {
0683                 p |= CATCH_FORWARD(rhs);
0684                 return CATCH_MOVE(p);
0685             }
0686 
0687             std::vector<Detail::HelpColumns> getHelpColumns() const;
0688 
0689             void writeToStream(std::ostream& os) const;
0690 
0691             friend auto operator<<(std::ostream& os, Parser const& parser)
0692                 -> std::ostream& {
0693                 parser.writeToStream(os);
0694                 return os;
0695             }
0696 
0697             Detail::Result validate() const override;
0698 
0699             using ParserBase::parse;
0700             Detail::InternalParseResult
0701                 parse(std::string const& exeName,
0702                       Detail::TokenStream tokens) const override;
0703         };
0704 
0705         /**
0706          * Wrapper over argc + argv, assumes that the inputs outlive it
0707          */
0708         class Args {
0709             friend Detail::TokenStream;
0710             StringRef m_exeName;
0711             std::vector<StringRef> m_args;
0712 
0713         public:
0714             Args(int argc, char const* const* argv);
0715             // Helper constructor for testing
0716             Args(std::initializer_list<StringRef> args);
0717 
0718             StringRef exeName() const { return m_exeName; }
0719         };
0720 
0721 
0722         // Convenience wrapper for option parser that specifies the help option
0723         struct Help : Opt {
0724             Help(bool& showHelpFlag);
0725         };
0726 
0727         // Result type for parser operation
0728         using Detail::ParserResult;
0729 
0730         namespace Detail {
0731             template <typename DerivedT>
0732             template <typename T>
0733             Parser
0734                 ComposableParserImpl<DerivedT>::operator|(T const& other) const {
0735                 return Parser() | static_cast<DerivedT const&>(*this) | other;
0736             }
0737         }
0738 
0739     } // namespace Clara
0740 } // namespace Catch
0741 
0742 #if defined( __clang__ )
0743 #    pragma clang diagnostic pop
0744 #endif
0745 
0746 #if defined( __GNUC__ )
0747 #    pragma GCC diagnostic pop
0748 #endif
0749 
0750 #endif // CATCH_CLARA_HPP_INCLUDED