diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp index 0d7d4875..b65d9b19 100644 --- a/projects/SelfTest/CmdLineTests.cpp +++ b/projects/SelfTest/CmdLineTests.cpp @@ -52,41 +52,41 @@ namespace Clara { } template - struct IBoundMember { - virtual ~IBoundMember() {} + struct IArgFunction { + virtual ~IArgFunction() {} virtual void set( ConfigT& config, std::string const& value ) const = 0; virtual void setFlag( ConfigT& config ) const = 0; virtual bool takesArg() const = 0; - virtual IBoundMember* clone() const = 0; + virtual IArgFunction* clone() const = 0; }; template - class BoundField { + class BoundArgFunction { public: - BoundField( IBoundMember* _boundMember ) : boundMember( _boundMember ) {} - BoundField( BoundField const& other ) : boundMember( other.boundMember->clone() ) {} - BoundField& operator = ( BoundField const& other ) { - IBoundMember newMember = other.clone(); - delete boundMember; - boundMember = newMember; + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction newFunctionObj = other.clone(); + delete functionObj; + functionObj = newFunctionObj; return *this; } - ~BoundField() { delete boundMember; } + ~BoundArgFunction() { delete functionObj; } void set( ConfigT& config, std::string const& value ) const { - boundMember->set( config, value ); + functionObj->set( config, value ); } void setFlag( ConfigT& config ) const { - boundMember->setFlag( config ); + functionObj->setFlag( config ); } - bool takesArg() const { return boundMember->takesArg(); } + bool takesArg() const { return functionObj->takesArg(); } private: - IBoundMember* boundMember; + IArgFunction* functionObj; }; template - struct BoundDataMember : IBoundMember{ + struct BoundDataMember : IArgFunction{ BoundDataMember( M C::* _member ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { convertInto( stringValue, p.*member ); @@ -95,11 +95,11 @@ namespace Clara { convertInto( true, p.*member ); } virtual bool takesArg() const { return !IsBool::value; } - virtual IBoundMember* clone() const { return new BoundDataMember( *this ); } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } M C::* member; }; template - struct BoundUnaryMethod : IBoundMember{ + struct BoundUnaryMethod : IArgFunction{ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { typename RemoveConstRef::type value; @@ -112,11 +112,11 @@ namespace Clara { (p.*member)( value ); } virtual bool takesArg() const { return !IsBool::value; } - virtual IBoundMember* clone() const { return new BoundUnaryMethod( *this ); } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } void (C::*member)( M ); }; template - struct BoundNullaryMethod : IBoundMember{ + struct BoundNullaryMethod : IArgFunction{ BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { bool value; @@ -128,21 +128,42 @@ namespace Clara { (p.*member)(); } virtual bool takesArg() const { return false; } - virtual IBoundMember* clone() const { return new BoundNullaryMethod( *this ); } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } void (C::*member)(); }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; template - BoundField makeBoundField( M C::* _member ) { - return BoundField( new BoundDataMember( _member ) ); + BoundArgFunction makeBoundField( M C::* _member ) { + return BoundArgFunction( new BoundDataMember( _member ) ); } template - BoundField makeBoundField( void (C::*_member)( M ) ) { - return BoundField( new BoundUnaryMethod( _member ) ); + BoundArgFunction makeBoundField( void (C::*_member)( M ) ) { + return BoundArgFunction( new BoundUnaryMethod( _member ) ); } template - BoundField makeBoundField( void (C::*_member)() ) { - return BoundField( new BoundNullaryMethod( _member ) ); + BoundArgFunction makeBoundField( void (C::*_member)() ) { + return BoundArgFunction( new BoundNullaryMethod( _member ) ); + } + template + BoundArgFunction makeBoundField( void (*_function)( C& ) ) { + return BoundArgFunction( new BoundUnaryFunction( _function ) ); } } // namespace Detail @@ -228,7 +249,7 @@ namespace Clara { }; struct Arg { - Arg( Detail::BoundField const& _boundField ) : boundField( _boundField ) {} + Arg( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} bool hasShortName( std::string const& shortName ) const { for( std::vector::const_iterator @@ -280,7 +301,7 @@ namespace Clara { return oss.str(); } - Detail::BoundField boundField; + Detail::BoundArgFunction boundField; std::vector shortNames; std::string longName; std::string description; @@ -542,12 +563,14 @@ struct Config { std::vector warnings; std::vector testsOrTags; - void abortAfterFirst() { abortAfter = 1; } +// void abortAfterFirst() { abortAfter = 1; } void abortAfterX( int x ) { abortAfter = x; } void addWarning( std::string const& _warning ) { warnings.push_back( _warning ); } void addTestOrTags( std::string const& _testSpec ) { testsOrTags.push_back( _testSpec ); } }; +inline void abortAfterFirst( Config& config ) { config.abortAfter = 1; } + SCENARIO( "New Catch commandline interface", "[cli]" ) { @@ -589,10 +612,10 @@ SCENARIO( "New Catch commandline interface", "[cli]" ) { .describe( "output filename" ) .shortOpt( "o") .longOpt( "out" ) - .argName( "file name" ); + .argName( "filename" ); cli.bind( &Config::reporter ) - .describe( "e.g. console | xml | junit" ) + .describe( "reporter to use - defaults to console" ) .shortOpt( "r") .longOpt( "reporter" ) .argName( "reporter name[:filename]" ); @@ -603,7 +626,7 @@ SCENARIO( "New Catch commandline interface", "[cli]" ) { .longOpt( "name" ) .argName( "name" ); - cli.bind( &Config::abortAfterFirst ) + cli.bind( &abortAfterFirst ) .describe( "abort at first failure" ) .shortOpt( "a") .longOpt( "abort" ); @@ -645,6 +668,14 @@ SCENARIO( "New Catch commandline interface", "[cli]" ) { CHECK( config.breakIntoDebugger ); } } + WHEN( "A flag is set via a nullary method" ) { + CHECK( config.abortAfter == 0 ); + + const char* argv[] = { "test", "-a" }; + parseInto( cli, argv, config ); + + REQUIRE( config.abortAfter == 1 ); + } } }