dev build 5
diff --git a/conanfile.py b/conanfile.py
index d1dfa81..5c7d993 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -4,7 +4,7 @@
 
 class CatchConan(ConanFile):
     name = "Catch"
-    version = "2.0.0-develop.4"
+    version = "2.0.0-develop.5"
     description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
     author = "philsquared"
     generators = "cmake"
diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp
index b635800..e684f3f 100644
--- a/include/internal/catch_version.cpp
+++ b/include/internal/catch_version.cpp
@@ -37,7 +37,7 @@
     }
 
     Version const& libraryVersion() {
-        static Version version( 2, 0, 0, "develop", 4 );
+        static Version version( 2, 0, 0, "develop", 5 );
         return version;
     }
 
diff --git a/single_include/catch.hpp b/single_include/catch.hpp
index e5ae619..f9568b0 100644
--- a/single_include/catch.hpp
+++ b/single_include/catch.hpp
@@ -1,6 +1,6 @@
 /*
- *  Catch v2.0.0-develop.4
- *  Generated: 2017-09-19 17:37:34.480115
+ *  Catch v2.0.0-develop.5
+ *  Generated: 2017-10-12 13:05:08.135067
  *  ----------------------------------------------------------
  *  This file has been merged from multiple headers. Please don't edit it directly
  *  Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved.
@@ -480,7 +480,6 @@
 #include <sstream>
 #include <vector>
 #include <cstddef>
-#include <tuple>
 #include <type_traits>
 #include <string>
 
@@ -749,7 +748,53 @@
         }
     };
 
-    // === Pair ===
+    template<typename T>
+    struct EnumStringMaker {
+        static std::string convert(const T& t) {
+            return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
+        }
+    };
+
+#ifdef __OBJC__
+    template<>
+    struct StringMaker<NSString*> {
+        static std::string convert(NSString * nsstring) {
+            if (!nsstring)
+                return "nil";
+            return std::string("@") + [nsstring UTF8String];
+        }
+    };
+    template<>
+    struct StringMaker<NSObject*> {
+        static std::string convert(NSObject* nsObject) {
+            return ::Catch::Detail::stringify([nsObject description]);
+        }
+
+    };
+    namespace Detail {
+        inline std::string stringify( NSString* nsstring ) {
+            return StringMaker<NSString*>::convert( nsstring );
+        }
+
+    } // namespace Detail
+#endif // __OBJC__
+
+} // namespace Catch
+
+//////////////////////////////////////////////////////
+// Separate std-lib types stringification, so it can be selectively enabled
+// This means that we do not bring in
+
+#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
+#  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
+#  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
+#  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#endif
+
+// Separate std::pair specialization
+#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
+#include <utility>
+namespace Catch {
     template<typename T1, typename T2>
     struct StringMaker<std::pair<T1, T2> > {
         static std::string convert(const std::pair<T1, T2>& pair) {
@@ -762,7 +807,13 @@
             return oss.str();
         }
     };
+}
+#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
 
+// Separate std::tuple specialization
+#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
+#include <tuple>
+namespace Catch {
     namespace Detail {
         template<
             typename Tuple,
@@ -797,39 +848,124 @@
             return os.str();
         }
     };
+}
+#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
 
-    template<typename T>
-    struct EnumStringMaker {
-        static std::string convert(const T& t) {
-            return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
+// Separate std::chrono::duration specialization
+#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#include <ctime>
+#include <ratio>
+#include <chrono>
+
+template <class Ratio>
+struct ratio_string {
+    static std::string symbol();
+};
+
+template <class Ratio>
+std::string ratio_string<Ratio>::symbol() {
+    std::ostringstream oss;
+    oss << '[' << Ratio::num << '/'
+        << Ratio::den << ']';
+    return oss.str();
+}
+template <>
+struct ratio_string<std::atto> {
+    static std::string symbol() { return "a"; }
+};
+template <>
+struct ratio_string<std::femto> {
+    static std::string symbol() { return "f"; }
+};
+template <>
+struct ratio_string<std::pico> {
+    static std::string symbol() { return "p"; }
+};
+template <>
+struct ratio_string<std::nano> {
+    static std::string symbol() { return "n"; }
+};
+template <>
+struct ratio_string<std::micro> {
+    static std::string symbol() { return "u"; }
+};
+template <>
+struct ratio_string<std::milli> {
+    static std::string symbol() { return "m"; }
+};
+
+namespace Catch {
+    ////////////
+    // std::chrono::duration specializations
+    template<typename Value, typename Ratio>
+    struct StringMaker<std::chrono::duration<Value, Ratio>> {
+        static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
+            std::ostringstream oss;
+            oss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
+            return oss.str();
+        }
+    };
+    template<typename Value>
+    struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
+        static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
+            std::ostringstream oss;
+            oss << duration.count() << " s";
+            return oss.str();
+        }
+    };
+    template<typename Value>
+    struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
+        static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
+            std::ostringstream oss;
+            oss << duration.count() << " m";
+            return oss.str();
+        }
+    };
+    template<typename Value>
+    struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
+        static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
+            std::ostringstream oss;
+            oss << duration.count() << " h";
+            return oss.str();
         }
     };
 
-#ifdef __OBJC__
-    template<>
-    struct StringMaker<NSString*> {
-        static std::string convert(NSString * nsstring) {
-            if (!nsstring)
-                return "nil";
-            return std::string("@") + [nsstring UTF8String];
+    ////////////
+    // std::chrono::time_point specialization
+    // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
+    template<typename Clock, typename Duration>
+    struct StringMaker<std::chrono::time_point<Clock, Duration>> {
+        static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
+            return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
         }
     };
-    template<>
-    struct StringMaker<NSObject*> {
-        static std::string convert(NSObject* nsObject) {
-            return ::Catch::Detail::stringify([nsObject description]);
-        }
+    // std::chrono::time_point<system_clock> specialization
+    template<typename Duration>
+    struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
+        static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
+            auto converted = std::chrono::system_clock::to_time_t(time_point);
 
+#ifdef _MSC_VER
+            std::tm timeInfo = {};
+            gmtime_s(&timeInfo, &converted);
+#else
+            std::tm* timeInfo = std::gmtime(&converted);
+#endif
+
+            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
+            char timeStamp[timeStampSize];
+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+#ifdef _MSC_VER
+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+#else
+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+#endif
+            return std::string(timeStamp);
+        }
     };
-    namespace Detail {
-        inline std::string stringify( NSString* nsstring ) {
-            return StringMaker<NSString*>::convert( nsstring );
-        }
-
-    } // namespace Detail
-#endif // __OBJC__
-
-} // namespace Catch
+}
+#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
 
 #ifdef _MSC_VER
 #pragma warning(pop)
@@ -1614,6 +1750,7 @@
         static std::string translatorName( signature )
 #endif
 
+#include <exception>
 #include <string>
 #include <vector>
 
@@ -1646,7 +1783,7 @@
             std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
                 try {
                     if( it == itEnd )
-                        throw;
+                        std::rethrow_exception(std::current_exception());
                     else
                         return (*it)->translate( it+1, itEnd );
                 }
@@ -4205,6 +4342,10 @@
 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
 #endif
 
+#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+
 // ----------- #included from clara_textflow.hpp -----------
 
 // TextFlowCpp
@@ -4538,9 +4679,8 @@
 #include <set>
 #include <algorithm>
 
-#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
-#define CLARA_PLATFORM_WINDOWS
-
+#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
+#define CATCH_PLATFORM_WINDOWS
 #endif
 
 namespace Catch { namespace clara {
@@ -4548,15 +4688,15 @@
 
     // Traits for extracting arg and return type of lambdas (for single argument lambdas)
     template<typename L>
-    struct UnaryLambdaTraits : UnaryLambdaTraits<decltype(&L::operator())> {};
+    struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
 
     template<typename ClassT, typename ReturnT, typename... Args>
-    struct UnaryLambdaTraits<ReturnT(ClassT::*)(Args...) const> {
+    struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
         static const bool isValid = false;
     };
 
     template<typename ClassT, typename ReturnT, typename ArgT>
-    struct UnaryLambdaTraits<ReturnT(ClassT::*)(ArgT) const> {
+    struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
         static const bool isValid = true;
         using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
         using ReturnType = ReturnT;
@@ -4571,13 +4711,13 @@
         std::vector<std::string> m_args;
 
     public:
-        Args(int argc, char *argv[]) {
+        Args( int argc, char *argv[] ) {
             m_exeName = argv[0];
-            for (int i = 1; i < argc; ++i)
-                m_args.push_back(argv[i]);
+            for( int i = 1; i < argc; ++i )
+                m_args.push_back( argv[i] );
         }
 
-        Args(std::initializer_list<std::string> args)
+        Args( std::initializer_list<std::string> args )
         :   m_exeName( *args.begin() ),
             m_args( args.begin()+1, args.end() )
         {}
@@ -4605,40 +4745,40 @@
         std::vector<Token> m_tokenBuffer;
 
         void loadBuffer() {
-            m_tokenBuffer.resize(0);
+            m_tokenBuffer.resize( 0 );
 
             // Skip any empty strings
-            while (it != itEnd && it->empty())
+            while( it != itEnd && it->empty() )
                 ++it;
 
-            if (it != itEnd) {
+            if( it != itEnd ) {
                 auto const &next = *it;
-                if (next[0] == '-' || next[0] == '/') {
-                    auto delimiterPos = next.find_first_of(" :=");
-                    if (delimiterPos != std::string::npos) {
-                        m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)});
-                        m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)});
+                if( next[0] == '-' || next[0] == '/' ) {
+                    auto delimiterPos = next.find_first_of( " :=" );
+                    if( delimiterPos != std::string::npos ) {
+                        m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
+                        m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
                     } else {
-                        if (next[1] != '-' && next.size() > 2) {
+                        if( next[1] != '-' && next.size() > 2 ) {
                             std::string opt = "- ";
-                            for (size_t i = 1; i < next.size(); ++i) {
+                            for( size_t i = 1; i < next.size(); ++i ) {
                                 opt[1] = next[i];
-                                m_tokenBuffer.push_back({TokenType::Option, opt});
+                                m_tokenBuffer.push_back( { TokenType::Option, opt } );
                             }
                         } else {
-                            m_tokenBuffer.push_back({TokenType::Option, next});
+                            m_tokenBuffer.push_back( { TokenType::Option, next } );
                         }
                     }
                 } else {
-                    m_tokenBuffer.push_back({TokenType::Argument, next});
+                    m_tokenBuffer.push_back( { TokenType::Argument, next } );
                 }
             }
         }
 
     public:
-        explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
+        explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
 
-        TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) {
+        TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
             loadBuffer();
         }
 
@@ -4649,20 +4789,20 @@
         auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
 
         auto operator*() const -> Token {
-            assert(!m_tokenBuffer.empty());
+            assert( !m_tokenBuffer.empty() );
             return m_tokenBuffer.front();
         }
 
         auto operator->() const -> Token const * {
-            assert(!m_tokenBuffer.empty());
+            assert( !m_tokenBuffer.empty() );
             return &m_tokenBuffer.front();
         }
 
         auto operator++() -> TokenStream & {
-            if (m_tokenBuffer.size() >= 2) {
-                m_tokenBuffer.erase(m_tokenBuffer.begin());
+            if( m_tokenBuffer.size() >= 2 ) {
+                m_tokenBuffer.erase( m_tokenBuffer.begin() );
             } else {
-                if (it != itEnd)
+                if( it != itEnd )
                     ++it;
                 loadBuffer();
             }
@@ -4677,7 +4817,7 @@
         };
 
     protected:
-        ResultBase(Type type) : m_type(type) {}
+        ResultBase( Type type ) : m_type( type ) {}
         virtual ~ResultBase() = default;
 
         virtual void enforceOk() const = 0;
@@ -4694,28 +4834,28 @@
         }
 
     protected:
-        ResultValueBase(Type type) : ResultBase(type) {}
+        ResultValueBase( Type type ) : ResultBase( type ) {}
 
-        ResultValueBase(ResultValueBase const &other) : ResultBase(other) {
-            if (m_type == ResultBase::Ok)
-                new(&m_value) T(other.m_value);
+        ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
+            if( m_type == ResultBase::Ok )
+                new( &m_value ) T( other.m_value );
         }
 
-        ResultValueBase(Type, T const &value) : ResultBase(Ok) {
-            new(&m_value) T(value);
+        ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
+            new( &m_value ) T( value );
         }
 
-        auto operator=(ResultValueBase const &other) -> ResultValueBase & {
-            if (m_type == ResultBase::Ok)
+        auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
+            if( m_type == ResultBase::Ok )
                 m_value.~T();
             ResultBase::operator=(other);
-            if (m_type == ResultBase::Ok)
-                new(&m_value) T(other.m_value);
+            if( m_type == ResultBase::Ok )
+                new( &m_value ) T( other.m_value );
             return *this;
         }
 
         ~ResultValueBase() {
-            if (m_type == Ok)
+            if( m_type == Ok )
                 m_value.~T();
         }
 
@@ -4734,37 +4874,31 @@
     class BasicResult : public ResultValueBase<T> {
     public:
         template<typename U>
-        explicit BasicResult(BasicResult<U> const &other)
-                :   ResultValueBase<T>(other.type()),
-                    m_errorMessage(other.errorMessage()) {
-            assert(type() != ResultBase::Ok);
+        explicit BasicResult( BasicResult<U> const &other )
+        :   ResultValueBase<T>( other.type() ),
+            m_errorMessage( other.errorMessage() )
+        {
+            assert( type() != ResultBase::Ok );
         }
 
-        static auto ok() -> BasicResult { return {ResultBase::Ok}; }
-
         template<typename U>
-        static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; }
-
-        static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; }
-
-        static auto runtimeError(std::string const &message) -> BasicResult {
-            return {ResultBase::RuntimeError, message};
-        }
+        static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
+        static auto ok() -> BasicResult { return { ResultBase::Ok }; }
+        static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
+        static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
 
         explicit operator bool() const { return m_type == ResultBase::Ok; }
-
         auto type() const -> ResultBase::Type { return m_type; }
-
         auto errorMessage() const -> std::string { return m_errorMessage; }
 
     protected:
         virtual void enforceOk() const {
             // !TBD: If no exceptions, std::terminate here or something
-            switch (m_type) {
+            switch( m_type ) {
                 case ResultBase::LogicError:
-                    throw std::logic_error(m_errorMessage);
+                    throw std::logic_error( m_errorMessage );
                 case ResultBase::RuntimeError:
-                    throw std::runtime_error(m_errorMessage);
+                    throw std::runtime_error( m_errorMessage );
                 case ResultBase::Ok:
                     break;
             }
@@ -4772,10 +4906,11 @@
 
         std::string m_errorMessage; // Only populated if resultType is an error
 
-        BasicResult(ResultBase::Type type, std::string const &message)
-                : ResultValueBase<T>(type),
-                  m_errorMessage(message) {
-            assert(m_type != ResultBase::Ok);
+        BasicResult( ResultBase::Type type, std::string const &message )
+        :   ResultValueBase<T>(type),
+            m_errorMessage(message)
+        {
+            assert( m_type != ResultBase::Ok );
         }
 
         using ResultValueBase<T>::ResultValueBase;
@@ -4789,12 +4924,12 @@
     class ParseState {
     public:
 
-        ParseState(ParseResultType type, TokenStream const &remainingTokens)
-                : m_type(type),
-                  m_remainingTokens(remainingTokens) {}
+        ParseState( ParseResultType type, TokenStream const &remainingTokens )
+        : m_type(type),
+          m_remainingTokens( remainingTokens )
+        {}
 
         auto type() const -> ParseResultType { return m_type; }
-
         auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
 
     private:
@@ -4812,69 +4947,62 @@
     };
 
     template<typename T>
-    inline auto convertInto(std::string const &source, T& target) -> ParserResult {
+    inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
         std::stringstream ss;
         ss << source;
         ss >> target;
-        if (ss.fail())
-            return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type");
+        if( ss.fail() )
+            return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
         else
-            return ParserResult::ok(ParseResultType::Matched);
+            return ParserResult::ok( ParseResultType::Matched );
     }
-    inline auto convertInto(std::string const &source, std::string& target) -> ParserResult {
+    inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
         target = source;
-        return ParserResult::ok(ParseResultType::Matched);
+        return ParserResult::ok( ParseResultType::Matched );
     }
-    inline auto convertInto(std::string const &source, bool &target) -> ParserResult {
+    inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
         std::string srcLC = source;
-        std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast<char>( ::tolower(c) ); } );
+        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
         if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
             target = true;
         else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
             target = false;
         else
-            return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'");
-        return ParserResult::ok(ParseResultType::Matched);
+            return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
+        return ParserResult::ok( ParseResultType::Matched );
     }
 
     struct BoundRefBase {
         BoundRefBase() = default;
-
-        BoundRefBase(BoundRefBase const &) = delete;
-
-        BoundRefBase(BoundRefBase &&) = delete;
-
-        BoundRefBase &operator=(BoundRefBase const &) = delete;
-
-        BoundRefBase &operator=(BoundRefBase &&) = delete;
+        BoundRefBase( BoundRefBase const & ) = delete;
+        BoundRefBase( BoundRefBase && ) = delete;
+        BoundRefBase &operator=( BoundRefBase const & ) = delete;
+        BoundRefBase &operator=( BoundRefBase && ) = delete;
 
         virtual ~BoundRefBase() = default;
 
         virtual auto isFlag() const -> bool = 0;
-
         virtual auto isContainer() const -> bool { return false; }
-
-        virtual auto setValue(std::string const &arg) -> ParserResult = 0;
-
-        virtual auto setFlag(bool flag) -> ParserResult = 0;
+        virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
+        virtual auto setFlag( bool flag ) -> ParserResult = 0;
     };
 
     struct BoundValueRefBase : BoundRefBase {
         auto isFlag() const -> bool override { return false; }
 
-        auto setFlag(bool) -> ParserResult override {
-            return ParserResult::logicError("Flags can only be set on boolean fields");
+        auto setFlag( bool ) -> ParserResult override {
+            return ParserResult::logicError( "Flags can only be set on boolean fields" );
         }
     };
 
     struct BoundFlagRefBase : BoundRefBase {
         auto isFlag() const -> bool override { return true; }
 
-        auto setValue(std::string const &arg) -> ParserResult override {
+        auto setValue( std::string const &arg ) -> ParserResult override {
             bool flag;
-            auto result = convertInto(arg, flag);
-            if (result)
-                setFlag(flag);
+            auto result = convertInto( arg, flag );
+            if( result )
+                setFlag( flag );
             return result;
         }
     };
@@ -4883,10 +5011,10 @@
     struct BoundRef : BoundValueRefBase {
         T &m_ref;
 
-        explicit BoundRef(T &ref) : m_ref(ref) {}
+        explicit BoundRef( T &ref ) : m_ref( ref ) {}
 
-        auto setValue(std::string const &arg) -> ParserResult override {
-            return convertInto(arg, m_ref);
+        auto setValue( std::string const &arg ) -> ParserResult override {
+            return convertInto( arg, m_ref );
         }
     };
 
@@ -4894,15 +5022,15 @@
     struct BoundRef<std::vector<T>> : BoundValueRefBase {
         std::vector<T> &m_ref;
 
-        explicit BoundRef(std::vector<T> &ref) : m_ref(ref) {}
+        explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
 
         auto isContainer() const -> bool override { return true; }
 
-        auto setValue(std::string const &arg) -> ParserResult override {
+        auto setValue( std::string const &arg ) -> ParserResult override {
             T temp;
-            auto result = convertInto(arg, temp);
-            if (result)
-                m_ref.push_back(temp);
+            auto result = convertInto( arg, temp );
+            if( result )
+                m_ref.push_back( temp );
             return result;
         }
     };
@@ -4910,40 +5038,40 @@
     struct BoundFlagRef : BoundFlagRefBase {
         bool &m_ref;
 
-        explicit BoundFlagRef(bool &ref) : m_ref(ref) {}
+        explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
 
-        auto setFlag(bool flag) -> ParserResult override {
+        auto setFlag( bool flag ) -> ParserResult override {
             m_ref = flag;
-            return ParserResult::ok(ParseResultType::Matched);
+            return ParserResult::ok( ParseResultType::Matched );
         }
     };
 
     template<typename ReturnType>
     struct LambdaInvoker {
-        static_assert(std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult");
+        static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
 
         template<typename L, typename ArgType>
-        static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult {
-            return lambda(arg);
+        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
+            return lambda( arg );
         }
     };
 
     template<>
     struct LambdaInvoker<void> {
         template<typename L, typename ArgType>
-        static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult {
-            lambda(arg);
-            return ParserResult::ok(ParseResultType::Matched);
+        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
+            lambda( arg );
+            return ParserResult::ok( ParseResultType::Matched );
         }
     };
 
     template<typename ArgType, typename L>
-    inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult {
+    inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
         ArgType temp;
-        auto result = convertInto(arg, temp);
+        auto result = convertInto( arg, temp );
         return !result
-               ? result
-               : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(lambda, temp);
+           ? result
+           : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
     };
 
     template<typename L>
@@ -4951,10 +5079,10 @@
         L m_lambda;
 
         static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
-        explicit BoundLambda(L const &lambda) : m_lambda(lambda) {}
+        explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
 
-        auto setValue(std::string const &arg) -> ParserResult override {
-            return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg);
+        auto setValue( std::string const &arg ) -> ParserResult override {
+            return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
         }
     };
 
@@ -4965,16 +5093,14 @@
         static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
         static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
 
-        explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {}
+        explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
 
-        auto setFlag(bool flag) -> ParserResult override {
-            return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag);
+        auto setFlag( bool flag ) -> ParserResult override {
+            return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
         }
     };
 
-    enum class Optionality {
-        Optional, Required
-    };
+    enum class Optionality { Optional, Required };
 
     struct Parser;
 
@@ -4985,8 +5111,8 @@
         virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult  = 0;
         virtual auto cardinality() const -> size_t { return 1; }
 
-        auto parse(Args const &args) const -> InternalParseResult {
-            return parse( args.exeName(), TokenStream(args));
+        auto parse( Args const &args ) const -> InternalParseResult {
+            return parse( args.exeName(), TokenStream( args ) );
         }
     };
 
@@ -4994,7 +5120,7 @@
     class ComposableParserImpl : public ParserBase {
     public:
         template<typename T>
-        auto operator+(T const &other) const -> Parser;
+        auto operator|( T const &other ) const -> Parser;
     };
 
     // Common code and state for Args and Opts
@@ -5006,17 +5132,22 @@
         std::string m_hint;
         std::string m_description;
 
-        explicit ParserRefImpl(std::shared_ptr<BoundRefBase> const &ref) : m_ref(ref) {}
+        explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
 
     public:
         template<typename T>
-        ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared<BoundRef<T>>(ref)), m_hint(hint) {}
+        ParserRefImpl( T &ref, std::string const &hint )
+        :   m_ref( std::make_shared<BoundRef<T>>( ref ) ),
+            m_hint( hint )
+        {}
 
         template<typename LambdaT>
-        ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)),
-                                                                     m_hint(hint) {}
+        ParserRefImpl( LambdaT const &ref, std::string const &hint )
+        :   m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
+            m_hint(hint)
+        {}
 
-        auto operator()(std::string const &description) -> DerivedT & {
+        auto operator()( std::string const &description ) -> DerivedT & {
             m_description = description;
             return static_cast<DerivedT &>( *this );
         }
@@ -5036,7 +5167,7 @@
         }
 
         auto cardinality() const -> size_t override {
-            if (m_ref->isContainer())
+            if( m_ref->isContainer() )
                 return 0;
             else
                 return 1;
@@ -5051,13 +5182,13 @@
 
         template<typename LambdaT>
         static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
-            return std::make_shared<BoundLambda<LambdaT>>(lambda);
+            return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
         }
 
     public:
-        ExeName() : m_name(std::make_shared<std::string>("<executable>")) {}
+        ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
 
-        explicit ExeName(std::string &ref) : ExeName() {
+        explicit ExeName( std::string &ref ) : ExeName() {
             m_ref = std::make_shared<BoundRef<std::string>>( ref );
         }
 
@@ -5068,14 +5199,14 @@
 
         // The exe name is not parsed out of the normal tokens, but is handled specially
         auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
-            return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
+            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
         }
 
         auto name() const -> std::string { return *m_name; }
         auto set( std::string const& newName ) -> ParserResult {
 
             auto lastSlash = newName.find_last_of( "\\/" );
-            auto filename = (lastSlash == std::string::npos)
+            auto filename = ( lastSlash == std::string::npos )
                     ? newName
                     : newName.substr( lastSlash+1 );
 
@@ -5091,27 +5222,27 @@
     public:
         using ParserRefImpl::ParserRefImpl;
 
-        auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override {
+        auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {
             auto validationResult = validate();
-            if (!validationResult)
-                return InternalParseResult(validationResult);
+            if( !validationResult )
+                return InternalParseResult( validationResult );
 
             auto remainingTokens = tokens;
             auto const &token = *remainingTokens;
-            if (token.type != TokenType::Argument)
-                return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
+            if( token.type != TokenType::Argument )
+                return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
 
-            auto result = m_ref->setValue(remainingTokens->token);
-            if (!result)
-                return InternalParseResult(result);
+            auto result = m_ref->setValue( remainingTokens->token );
+            if( !result )
+                return InternalParseResult( result );
             else
-                return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens));
+                return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
         }
     };
 
-    inline auto normaliseOpt(std::string const &optName) -> std::string {
-        if (optName[0] == '/')
-            return "-" + optName.substr(1);
+    inline auto normaliseOpt( std::string const &optName ) -> std::string {
+        if( optName[0] == '/' )
+            return "-" + optName.substr( 1 );
         else
             return optName;
     }
@@ -5122,9 +5253,9 @@
 
     public:
         template<typename LambdaT>
-        explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {}
+        explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
 
-        explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
+        explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
 
         template<typename LambdaT>
         Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
@@ -5132,34 +5263,34 @@
         template<typename T>
         Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
 
-        auto operator[](std::string const &optName) -> Opt & {
-            m_optNames.push_back(optName);
+        auto operator[]( std::string const &optName ) -> Opt & {
+            m_optNames.push_back( optName );
             return *this;
         }
 
         auto getHelpColumns() const -> std::vector<HelpColumns> {
             std::ostringstream oss;
             bool first = true;
-            for (auto const &opt : m_optNames) {
+            for( auto const &opt : m_optNames ) {
                 if (first)
                     first = false;
                 else
                     oss << ", ";
                 oss << opt;
             }
-            if (!m_hint.empty())
+            if( !m_hint.empty() )
                 oss << " <" << m_hint << ">";
-            return {{oss.str(), m_description}};
+            return { { oss.str(), m_description } };
         }
 
-        auto isMatch(std::string const &optToken) const -> bool {
-#ifdef CLARA_PLATFORM_WINDOWS
+        auto isMatch( std::string const &optToken ) const -> bool {
+#ifdef CATCH_PLATFORM_WINDOWS
             auto normalisedToken = normaliseOpt( optToken );
 #else
             auto const &normalisedToken = optToken;
 #endif
-            for (auto const &name : m_optNames) {
-                if (normaliseOpt(name) == normalisedToken)
+            for( auto const &name : m_optNames ) {
+                if( normaliseOpt( name ) == normalisedToken )
                     return true;
             }
             return false;
@@ -5169,46 +5300,46 @@
 
         auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
             auto validationResult = validate();
-            if (!validationResult)
-                return InternalParseResult(validationResult);
+            if( !validationResult )
+                return InternalParseResult( validationResult );
 
             auto remainingTokens = tokens;
-            if (remainingTokens && remainingTokens->type == TokenType::Option) {
+            if( remainingTokens && remainingTokens->type == TokenType::Option ) {
                 auto const &token = *remainingTokens;
-                if (isMatch(token.token)) {
-                    if (m_ref->isFlag()) {
-                        auto result = m_ref->setFlag(true);
-                        if (!result)
-                            return InternalParseResult(result);
-                        if (result.value() == ParseResultType::ShortCircuitAll)
-                            return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
+                if( isMatch(token.token ) ) {
+                    if( m_ref->isFlag() ) {
+                        auto result = m_ref->setFlag( true );
+                        if( !result )
+                            return InternalParseResult( result );
+                        if( result.value() == ParseResultType::ShortCircuitAll )
+                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
                     } else {
                         ++remainingTokens;
-                        if (!remainingTokens)
-                            return InternalParseResult::runtimeError("Expected argument following " + token.token);
+                        if( !remainingTokens )
+                            return InternalParseResult::runtimeError( "Expected argument following " + token.token );
                         auto const &argToken = *remainingTokens;
-                        if (argToken.type != TokenType::Argument)
-                            return InternalParseResult::runtimeError("Expected argument following " + token.token);
-                        auto result = m_ref->setValue(argToken.token);
-                        if (!result)
-                            return InternalParseResult(result);
-                        if (result.value() == ParseResultType::ShortCircuitAll)
-                            return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
+                        if( argToken.type != TokenType::Argument )
+                            return InternalParseResult::runtimeError( "Expected argument following " + token.token );
+                        auto result = m_ref->setValue( argToken.token );
+                        if( !result )
+                            return InternalParseResult( result );
+                        if( result.value() == ParseResultType::ShortCircuitAll )
+                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
                     }
-                    return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens));
+                    return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
                 }
             }
-            return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
+            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
         }
 
         auto validate() const -> Result override {
-            if (m_optNames.empty())
-                return Result::logicError("No options supplied to Opt");
-            for (auto const &name : m_optNames) {
-                if (name.empty())
-                    return Result::logicError("Option name cannot be empty");
-                if (name[0] != '-' && name[0] != '/')
-                    return Result::logicError("Option name must begin with '-' or '/'");
+            if( m_optNames.empty() )
+                return Result::logicError( "No options supplied to Opt" );
+            for( auto const &name : m_optNames ) {
+                if( name.empty() )
+                    return Result::logicError( "Option name cannot be empty" );
+                if( name[0] != '-' && name[0] != '/' )
+                    return Result::logicError( "Option name must begin with '-' or '/'" );
             }
             return ParserRefImpl::validate();
         }
@@ -5217,11 +5348,11 @@
     struct Help : Opt {
         Help( bool &showHelpFlag )
         :   Opt([&]( bool flag ) {
-            showHelpFlag = flag;
-                return ParserResult::ok(ParseResultType::ShortCircuitAll);
+                showHelpFlag = flag;
+                return ParserResult::ok( ParseResultType::ShortCircuitAll );
             })
         {
-            static_cast<Opt &>(*this)
+            static_cast<Opt &>( *this )
                     ("display usage information")
                     ["-?"]["-h"]["--help"]
                     .optional();
@@ -5234,61 +5365,61 @@
         std::vector<Opt> m_options;
         std::vector<Arg> m_args;
 
-        auto operator+=(ExeName const &exeName) -> Parser & {
+        auto operator|=( ExeName const &exeName ) -> Parser & {
             m_exeName = exeName;
             return *this;
         }
 
-        auto operator+=(Arg const &arg) -> Parser & {
+        auto operator|=( Arg const &arg ) -> Parser & {
             m_args.push_back(arg);
             return *this;
         }
 
-        auto operator+=(Opt const &opt) -> Parser & {
+        auto operator|=( Opt const &opt ) -> Parser & {
             m_options.push_back(opt);
             return *this;
         }
 
-        auto operator+=(Parser const &other) -> Parser & {
+        auto operator|=( Parser const &other ) -> Parser & {
             m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
             m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
             return *this;
         }
 
         template<typename T>
-        auto operator+(T const &other) const -> Parser {
-            return Parser(*this) += other;
+        auto operator|( T const &other ) const -> Parser {
+            return Parser( *this ) |= other;
         }
 
         auto getHelpColumns() const -> std::vector<HelpColumns> {
             std::vector<HelpColumns> cols;
             for (auto const &o : m_options) {
                 auto childCols = o.getHelpColumns();
-                cols.insert(cols.end(), childCols.begin(), childCols.end());
+                cols.insert( cols.end(), childCols.begin(), childCols.end() );
             }
             return cols;
         }
 
-        void writeToStream(std::ostream &os) const {
+        void writeToStream( std::ostream &os ) const {
             if (!m_exeName.name().empty()) {
                 os << "usage:\n" << "  " << m_exeName.name() << " ";
                 bool required = true, first = true;
-                for (auto const &arg : m_args) {
+                for( auto const &arg : m_args ) {
                     if (first)
                         first = false;
                     else
                         os << " ";
-                    if (arg.isOptional() && required) {
+                    if( arg.isOptional() && required ) {
                         os << "[";
                         required = false;
                     }
                     os << "<" << arg.hint() << ">";
-                    if (arg.cardinality() == 0)
+                    if( arg.cardinality() == 0 )
                         os << " ... ";
                 }
-                if (!required)
+                if( !required )
                     os << "]";
-                if (!m_options.empty())
+                if( !m_options.empty() )
                     os << " options";
                 os << "\n\nwhere options are:" << std::endl;
             }
@@ -5296,32 +5427,32 @@
             auto rows = getHelpColumns();
             size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
             size_t optWidth = 0;
-            for (auto const &cols : rows)
+            for( auto const &cols : rows )
                 optWidth = std::max(optWidth, cols.left.size() + 2);
 
-            for (auto const &cols : rows) {
+            for( auto const &cols : rows ) {
                 auto row =
-                        TextFlow::Column(cols.left).width(optWidth).indent(2) +
+                        TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
                         TextFlow::Spacer(4) +
-                        TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
+                        TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
                 os << row << std::endl;
             }
         }
 
-        friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & {
-            parser.writeToStream(os);
+        friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {
+            parser.writeToStream( os );
             return os;
         }
 
         auto validate() const -> Result override {
-            for (auto const &opt : m_options) {
+            for( auto const &opt : m_options ) {
                 auto result = opt.validate();
-                if (!result)
+                if( !result )
                     return result;
             }
-            for (auto const &arg : m_args) {
+            for( auto const &arg : m_args ) {
                 auto result = arg.validate();
-                if (!result)
+                if( !result )
                     return result;
             }
             return Result::ok();
@@ -5329,47 +5460,47 @@
 
         using ParserBase::parse;
 
-        auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override {
-            std::vector<ParserBase const *> allParsers;
-            allParsers.reserve(m_args.size() + m_options.size());
-            std::set<ParserBase const *> requiredParsers;
+        auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
 
-            for (auto const &opt : m_options) {
-                allParsers.push_back(&opt);
-                if (!opt.isOptional())
-                    requiredParsers.insert(&opt);
-            }
+            struct ParserInfo {
+                ParserBase const* parser = nullptr;
+                size_t count = 0;
+            };
+            const size_t totalParsers = m_options.size() + m_args.size();
+            assert( totalParsers < 512 );
+            // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
+            ParserInfo parseInfos[512];
 
-            size_t optionalArgs = 0;
-            for (auto const &arg : m_args) {
-                allParsers.push_back(&arg);
-                if (!arg.isOptional()) {
-                    if (optionalArgs > 0)
-                        return InternalParseResult::logicError(
-                                "Required arguments must preceed any optional arguments");
-                    else
-                        ++optionalArgs;
-                    requiredParsers.insert(&arg);
-                }
+            {
+                size_t i = 0;
+                for (auto const &opt : m_options) parseInfos[i++].parser = &opt;
+                for (auto const &arg : m_args) parseInfos[i++].parser = &arg;
             }
 
             m_exeName.set( exeName );
 
-            auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
-            while (result.value().remainingTokens()) {
-                auto remainingTokenCount = result.value().remainingTokens().count();
-                for (auto parser : allParsers) {
-                    result = parser->parse( exeName, result.value().remainingTokens() );
-                    if (!result || result.value().type() != ParseResultType::NoMatch) {
-                        if (parser->cardinality() == 1)
-                            allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser),
-                                             allParsers.end());
-                        requiredParsers.erase(parser);
-                        break;
+            auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
+            while( result.value().remainingTokens() ) {
+                bool tokenParsed = false;
+
+                for( size_t i = 0; i < totalParsers; ++i ) {
+                    auto&  parseInfo = parseInfos[i];
+                    if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
+                        result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
+                        if (!result)
+                            return result;
+                        if (result.value().type() != ParseResultType::NoMatch) {
+                            tokenParsed = true;
+                            ++parseInfo.count;
+                            break;
+                        }
                     }
                 }
-                if (!result || remainingTokenCount == result.value().remainingTokens().count())
+
+                if( result.value().type() == ParseResultType::ShortCircuitAll )
                     return result;
+                if( !tokenParsed )
+                    return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
             }
             // !TBD Check missing required options
             return result;
@@ -5378,8 +5509,8 @@
 
     template<typename DerivedT>
     template<typename T>
-    auto ComposableParserImpl<DerivedT>::operator+(T const &other) const -> Parser {
-        return Parser() + static_cast<DerivedT const &>( *this ) + other;
+    auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {
+        return Parser() | static_cast<DerivedT const &>( *this ) | other;
     }
 } // namespace detail
 
@@ -5516,84 +5647,84 @@
 
         auto cli
             = ExeName( config.processName )
-            + Help( config.showHelp )
-            + Opt( config.listTests )
+            | Help( config.showHelp )
+            | Opt( config.listTests )
                 ["-l"]["--list-tests"]
                 ( "list all/matching test cases" )
-            + Opt( config.listTags )
+            | Opt( config.listTags )
                 ["-t"]["--list-tags"]
                 ( "list all/matching tags" )
-            + Opt( config.showSuccessfulTests )
+            | Opt( config.showSuccessfulTests )
                 ["-s"]["--success"]
                 ( "include successful tests in output" )
-            + Opt( config.shouldDebugBreak )
+            | Opt( config.shouldDebugBreak )
                 ["-b"]["--break"]
                 ( "break into debugger on failure" )
-            + Opt( config.noThrow )
+            | Opt( config.noThrow )
                 ["-e"]["--nothrow"]
                 ( "skip exception tests" )
-            + Opt( config.showInvisibles )
+            | Opt( config.showInvisibles )
                 ["-i"]["--invisibles"]
                 ( "show invisibles (tabs, newlines)" )
-            + Opt( config.outputFilename, "filename" )
+            | Opt( config.outputFilename, "filename" )
                 ["-o"]["--out"]
                 ( "output filename" )
-            + Opt( config.reporterNames, "name" )
+            | Opt( config.reporterNames, "name" )
                 ["-r"]["--reporter"]
                 ( "reporter to use (defaults to console)" )
-            + Opt( config.name, "name" )
+            | Opt( config.name, "name" )
                 ["-n"]["--name"]
                 ( "suite name" )
-            + Opt( [&]( bool ){ config.abortAfter = 1; } )
+            | Opt( [&]( bool ){ config.abortAfter = 1; } )
                 ["-a"]["--abort"]
                 ( "abort at first failure" )
-            + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
+            | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
                 ["-x"]["--abortx"]
                 ( "abort after x failures" )
-            + Opt( setWarning, "warning name" )
+            | Opt( setWarning, "warning name" )
                 ["-w"]["--warn"]
                 ( "enable warnings" )
-            + Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
+            | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
                 ["-d"]["--durations"]
                 ( "show test durations" )
-            + Opt( loadTestNamesFromFile, "filename" )
+            | Opt( loadTestNamesFromFile, "filename" )
                 ["-f"]["--input-file"]
                 ( "load test names to run from a file" )
-            + Opt( config.filenamesAsTags )
+            | Opt( config.filenamesAsTags )
                 ["-#"]["--filenames-as-tags"]
                 ( "adds a tag for the filename" )
-            + Opt( config.sectionsToRun, "section name" )
+            | Opt( config.sectionsToRun, "section name" )
                 ["-c"]["--section"]
                 ( "specify section to run" )
-            + Opt( setVerbosity, "quiet|normal|high" )
+            | Opt( setVerbosity, "quiet|normal|high" )
                 ["-v"]["--verbosity"]
                 ( "set output verbosity" )
-            + Opt( config.listTestNamesOnly )
+            | Opt( config.listTestNamesOnly )
                 ["--list-test-names-only"]
                 ( "list all/matching test cases names only" )
-            + Opt( config.listReporters )
+            | Opt( config.listReporters )
                 ["--list-reporters"]
                 ( "list all reporters" )
-            + Opt( setTestOrder, "decl|lex|rand" )
+            | Opt( setTestOrder, "decl|lex|rand" )
                 ["--order"]
                 ( "test case order (defaults to decl)" )
-            + Opt( setRngSeed, "'time'|number" )
+            | Opt( setRngSeed, "'time'|number" )
                 ["--rng-seed"]
                 ( "set a specific seed for random numbers" )
-            + Opt( setColourUsage, "yes|no" )
+            | Opt( setColourUsage, "yes|no" )
                 ["--use-colour"]
                 ( "should output be colourised" )
-            + Opt( config.libIdentify )
+            | Opt( config.libIdentify )
                 ["--libidentify"]
                 ( "report name and version according to libidentify standard" )
-            + Opt( setWaitForKeypress, "start|exit|both" )
+            | Opt( setWaitForKeypress, "start|exit|both" )
                 ["--wait-for-keypress"]
                 ( "waits for a keypress before exiting" )
-            + Opt( config.benchmarkResolutionMultiple, "multiplier" )
+            | Opt( config.benchmarkResolutionMultiple, "multiplier" )
                 ["--benchmark-resolution-multiple"]
                 ( "multiple of clock resolution to run benchmarks" )
 
-            + Arg( config.testsOrTags, "test name|pattern|tags" )
+            | Arg( config.testsOrTags, "test name|pattern|tags" )
                 ( "which test or tests to use" );
 
         return cli;
@@ -5731,6 +5862,36 @@
 }
 
 // end catch_errno_guard.h
+// start catch_windows_h_proxy.h
+
+
+#if defined(CATCH_PLATFORM_WINDOWS)
+
+#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
+#  define CATCH_DEFINED_NOMINMAX
+#  define NOMINMAX
+#endif
+#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
+#  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+
+#ifdef CATCH_DEFINED_NOMINMAX
+#  undef NOMINMAX
+#endif
+#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+#  undef WIN32_LEAN_AND_MEAN
+#endif
+
+#endif // defined(CATCH_PLATFORM_WINDOWS)
+
+// end catch_windows_h_proxy.h
 namespace Catch {
     namespace {
 
@@ -5761,34 +5922,6 @@
 
 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
 
-// start catch_windows_h_proxy.h
-
-
-#if defined(CATCH_PLATFORM_WINDOWS)
-#  if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
-#    define CATCH_DEFINED_NOMINMAX
-#    define NOMINMAX
-#  endif
-#  if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
-#    define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
-#endif
-
-#ifdef __AFXDLL
-#include <AfxWin.h>
-#else
-#include <windows.h>
-#endif
-
-#ifdef CATCH_DEFINED_NOMINMAX
-#  undef NOMINMAX
-#endif
-#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
-#  undef WIN32_LEAN_AND_MEAN
-#endif
-
-// end catch_windows_h_proxy.h
 namespace Catch {
 namespace {
 
@@ -6220,7 +6353,7 @@
 #endif
         }
         catch( TestFailureException& ) {
-            throw;
+            std::rethrow_exception(std::current_exception());
         }
         catch( std::exception& ex ) {
             return ex.what();
@@ -6238,7 +6371,7 @@
 
     std::string ExceptionTranslatorRegistry::tryTranslators() const {
         if( m_translators.empty() )
-            throw;
+            std::rethrow_exception(std::current_exception());
         else
             return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
     }
@@ -6523,6 +6656,9 @@
 
         static std::set<Verbosity> getSupportedVerbosities();
 
+        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
+        void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override;
+
         void testRunStarting( TestRunInfo const& testRunInfo ) override;
         void testGroupStarting( GroupInfo const& groupInfo ) override;
         void testCaseStarting( TestCaseInfo const& testInfo ) override;
@@ -9649,7 +9785,7 @@
     }
 
     Version const& libraryVersion() {
-        static Version version( 2, 0, 0, "develop", 4 );
+        static Version version( 2, 0, 0, "develop", 5 );
         return version;
     }
 
@@ -11204,6 +11340,15 @@
             reporter->noMatchingTestCases( spec );
     }
 
+    void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
+        for( auto const& reporter : m_reporters )
+            reporter->benchmarkStarting( benchmarkInfo );
+    }
+    void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
+        for( auto const& reporter : m_reporters )
+            reporter->benchmarkEnded( benchmarkStats );
+    }
+
     void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) {
         for( auto const& reporter : m_reporters )
             reporter->testRunStarting( testRunInfo );
diff --git a/test_package/conanfile.py b/test_package/conanfile.py
index 2311ab7..96d9398 100644
--- a/test_package/conanfile.py
+++ b/test_package/conanfile.py
@@ -10,7 +10,7 @@
     settings = "os", "compiler", "arch", "build_type"
     username = getenv("CONAN_USERNAME", "philsquared")
     channel = getenv("CONAN_CHANNEL", "testing")
-    requires = "Catch/2.0.0-develop.4@%s/%s" % (username, channel)
+    requires = "Catch/2.0.0-develop.5@%s/%s" % (username, channel)
 
     def build(self):
         cmake = CMake(self)