Split out more headers into separate .cpp files
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6489e3a..9c56cca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -225,7 +225,9 @@
         ${HEADER_DIR}/internal/catch_tag_alias.cpp
         ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp
         ${HEADER_DIR}/internal/catch_test_case_info.cpp
+        ${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp
         ${HEADER_DIR}/internal/catch_test_case_tracker.cpp
+        ${HEADER_DIR}/internal/catch_test_registry.cpp
         ${HEADER_DIR}/internal/catch_test_spec.cpp
         ${HEADER_DIR}/internal/catch_test_spec_parser.cpp
         ${HEADER_DIR}/internal/catch_timer.cpp
diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp
new file mode 100644
index 0000000..d7cab1d
--- /dev/null
+++ b/include/internal/catch_test_case_registry_impl.cpp
@@ -0,0 +1,113 @@
+/*
+ *  Created by Martin on 25/07/2017
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "catch_test_case_registry_impl.hpp"
+
+#include "catch_context.h"
+#include "catch_interfaces_registry_hub.h"
+#include "catch_string_manip.h"
+#include "catch_test_case_info.h"
+
+#include <sstream>
+
+namespace Catch {
+
+    RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { return std::rand() % n; }
+    RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { return std::rand() % max(); }
+
+    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
+
+        std::vector<TestCase> sorted = unsortedTestCases;
+
+        switch( config.runOrder() ) {
+            case RunTests::InLexicographicalOrder:
+                std::sort( sorted.begin(), sorted.end() );
+                break;
+            case RunTests::InRandomOrder:
+                seedRng( config );
+                RandomNumberGenerator::shuffle( sorted );
+                break;
+            case RunTests::InDeclarationOrder:
+                // already in declaration order
+                break;
+        }
+        return sorted;
+    }
+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
+        return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
+    }
+
+    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
+        std::set<TestCase> seenFunctions;
+        for( auto const& function : functions ) {
+            auto prev = seenFunctions.insert( function );
+            CATCH_ENFORCE( prev.second,
+                    "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
+                    << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
+                    << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
+        }
+    }
+
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
+        std::vector<TestCase> filtered;
+        filtered.reserve( testCases.size() );
+        for( auto const& testCase : testCases )
+            if( matchTest( testCase, testSpec, config ) )
+                filtered.push_back( testCase );
+        return filtered;
+    }
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
+        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
+    }
+
+    void TestRegistry::registerTest( TestCase const& testCase ) {
+        std::string name = testCase.getTestCaseInfo().name;
+        if( name.empty() ) {
+            std::ostringstream oss;
+            oss << "Anonymous test case " << ++m_unnamedCount;
+            return registerTest( testCase.withName( oss.str() ) );
+        }
+        m_functions.push_back( testCase );
+    }
+
+    std::vector<TestCase> const& TestRegistry::getAllTests() const {
+        return m_functions;
+    }
+    std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
+        if( m_sortedFunctions.empty() )
+            enforceNoDuplicateTestCases( m_functions );
+
+        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
+            m_sortedFunctions = sortTests( config, m_functions );
+            m_currentSortOrder = config.runOrder();
+        }
+        return m_sortedFunctions;
+    }
+
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
+
+    void TestInvokerAsFunction::invoke() const {
+        m_testAsFunction();
+    }
+
+    std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
+        std::string className = classOrQualifiedMethodName;
+        if( startsWith( className, '&' ) )
+        {
+            std::size_t lastColons = className.rfind( "::" );
+            std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
+            if( penultimateColons == std::string::npos )
+                penultimateColons = 1;
+            className = className.substr( penultimateColons, lastColons-penultimateColons );
+        }
+        return className;
+    }
+
+} // end namespace Catch
diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp
index 7008ae9..27b64eb 100644
--- a/include/internal/catch_test_case_registry_impl.hpp
+++ b/include/internal/catch_test_case_registry_impl.hpp
@@ -9,28 +9,27 @@
 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
 
 #include "catch_test_registry.hpp"
-#include "catch_test_case_info.h"
 #include "catch_test_spec.hpp"
-#include "catch_context.h"
 #include "catch_interfaces_config.h"
-#include "catch_string_manip.h"
 
 #include <vector>
 #include <set>
-#include <sstream>
 #include <algorithm>
 
 
 namespace Catch {
 
-    struct RandomNumberGenerator {
-        typedef std::ptrdiff_t result_type;
+    class TestCase;
+    class IConfig;
 
-        result_type operator()( result_type n ) const { return std::rand() % n; }
+    struct RandomNumberGenerator {
+        using result_type = std::ptrdiff_t;
+
+        result_type operator()( result_type n ) const;
 
         static constexpr result_type min() { return 0; }
         static constexpr result_type max() { return 1000000; }
-        result_type operator()() const { return std::rand() % max(); }
+        result_type operator()() const;
         template<typename V>
         static void shuffle( V& vector ) {
             RandomNumberGenerator rng;
@@ -38,78 +37,22 @@
         }
     };
 
-    inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
+    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); 
+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
 
-        std::vector<TestCase> sorted = unsortedTestCases;
+    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
 
-        switch( config.runOrder() ) {
-            case RunTests::InLexicographicalOrder:
-                std::sort( sorted.begin(), sorted.end() );
-                break;
-            case RunTests::InRandomOrder:
-                seedRng( config );
-                RandomNumberGenerator::shuffle( sorted );
-                break;
-            case RunTests::InDeclarationOrder:
-                // already in declaration order
-                break;
-        }
-        return sorted;
-    }
-    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
-        return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
-    }
-
-    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
-        std::set<TestCase> seenFunctions;
-        for( auto const& function : functions ) {
-            auto prev = seenFunctions.insert( function );
-            CATCH_ENFORCE( prev.second,
-                    "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
-                    << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
-                    << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
-        }
-    }
-
-    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
-        std::vector<TestCase> filtered;
-        filtered.reserve( testCases.size() );
-        for( auto const& testCase : testCases )
-            if( matchTest( testCase, testSpec, config ) )
-                filtered.push_back( testCase );
-        return filtered;
-    }
-    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
-        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
-    }
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
 
     class TestRegistry : public ITestCaseRegistry {
     public:
-        virtual ~TestRegistry();
+        virtual ~TestRegistry() = default;
 
-        virtual void registerTest( TestCase const& testCase ) {
-            std::string name = testCase.getTestCaseInfo().name;
-            if( name.empty() ) {
-                std::ostringstream oss;
-                oss << "Anonymous test case " << ++m_unnamedCount;
-                return registerTest( testCase.withName( oss.str() ) );
-            }
-            m_functions.push_back( testCase );
-        }
+        virtual void registerTest( TestCase const& testCase );
 
-        std::vector<TestCase> const& getAllTests() const override {
-            return m_functions;
-        }
-        std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override {
-            if( m_sortedFunctions.empty() )
-                enforceNoDuplicateTestCases( m_functions );
-
-            if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
-                m_sortedFunctions = sortTests( config, m_functions );
-                m_currentSortOrder = config.runOrder();
-            }
-            return m_sortedFunctions;
-        }
+        std::vector<TestCase> const& getAllTests() const override;
+        std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;
 
     private:
         std::vector<TestCase> m_functions;
@@ -119,57 +62,21 @@
         std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
     };
 
-    TestRegistry::~TestRegistry() {}
-
-
     ///////////////////////////////////////////////////////////////////////////
 
     class TestInvokerAsFunction : public ITestInvoker {
         void(*m_testAsFunction)();
     public:
-        TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
+        TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;
 
-        void invoke() const override {
-            m_testAsFunction();
-        }
+        void invoke() const override;
     };
-    auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
-        return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
-    }
 
 
-    inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
-        std::string className = classOrQualifiedMethodName;
-        if( startsWith( className, '&' ) )
-        {
-            std::size_t lastColons = className.rfind( "::" );
-            std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
-            if( penultimateColons == std::string::npos )
-                penultimateColons = 1;
-            className = className.substr( penultimateColons, lastColons-penultimateColons );
-        }
-        return className;
-    }
+    std::string extractClassName( std::string const& classOrQualifiedMethodName );
 
     ///////////////////////////////////////////////////////////////////////////
 
-    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept
-    {
-        try {
-            getMutableRegistryHub()
-                    .registerTest(
-                        makeTestCase(
-                            invoker,
-                            extractClassName( classOrMethod.c_str() ),
-                            nameAndTags.name.c_str(),
-                            nameAndTags.tags.c_str(),
-                            lineInfo));
-        } catch (...) {
-            // Do not throw when constructing global objects, instead register the exception to be processed later
-            getMutableRegistryHub().registerStartupException( std::current_exception() );
-        }
-    }
-    AutoReg::~AutoReg() {}
 
 } // end namespace Catch
 
diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp
new file mode 100644
index 0000000..2851762
--- /dev/null
+++ b/include/internal/catch_test_registry.cpp
@@ -0,0 +1,35 @@
+/*
+ *  Created by Martin on 25/07/2017.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "catch_test_registry.hpp"
+#include "catch_test_case_registry_impl.hpp"
+#include "catch_interfaces_registry_hub.h"
+
+namespace Catch {
+
+    auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
+        return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
+    }
+
+    NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
+
+    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
+        try {
+            getMutableRegistryHub()
+                    .registerTest(
+                        makeTestCase(
+                            invoker,
+                            extractClassName( classOrMethod.c_str() ),
+                            nameAndTags.name.c_str(),
+                            nameAndTags.tags.c_str(),
+                            lineInfo));
+        } catch (...) {
+            // Do not throw when constructing global objects, instead register the exception to be processed later
+            getMutableRegistryHub().registerStartupException( std::current_exception() );
+        }
+    }
+}
diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp
index c8538a2..1cd5fa4 100644
--- a/include/internal/catch_test_registry.hpp
+++ b/include/internal/catch_test_registry.hpp
@@ -35,16 +35,14 @@
 }
 
 struct NameAndTags {
-
-    NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept : name( name_ ), tags( tags_ ) {}
-
+    NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept;
     StringRef name;
     StringRef tags;
 };
 
 struct AutoReg : NonCopyable {
     AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
-    ~AutoReg();
+    ~AutoReg() = default;
 };
 
 } // end namespace Catch