From 4ffe816a69c9f9cba8c49d6e5de3a395748a4b3b Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 1 Feb 2019 12:43:12 +0100
Subject: [PATCH] allow setting documentation to algorithm overloads

---
 .../src/registration/AlgoRegistration.hpp     | 60 ++++++++++---------
 .../NormalizationRegistration.hpp             | 28 +++------
 .../src/automaton/determinize/Determinize.cpp |  2 +-
 .../command/OverloadsIntrospectionCommand.h   |  2 +-
 alib2std/src/extensions/registration.hpp      | 43 ++++++++++++-
 aql2/src/prompt/ReadlinePromptCompletion.cpp  |  2 +-
 6 files changed, 85 insertions(+), 52 deletions(-)

diff --git a/alib2abstraction/src/registration/AlgoRegistration.hpp b/alib2abstraction/src/registration/AlgoRegistration.hpp
index 7ffc757299..d5c54e9f4d 100644
--- a/alib2abstraction/src/registration/AlgoRegistration.hpp
+++ b/alib2abstraction/src/registration/AlgoRegistration.hpp
@@ -1,14 +1,16 @@
 #ifndef _ALGO_REGISTRATION_HPP_
 #define _ALGO_REGISTRATION_HPP_
 
+#include <alib/registration>
+
 #include <registry/AlgorithmRegistry.hpp>
 
 #include <registration/NormalizationRegistration.hpp>
 
 namespace registration {
 
-class AlgoRegister {
-protected:
+class AlgoRegisterHelper {
+public:
 	template < size_t ParameterTypesNumber, class ... ParamNames, typename std::enable_if < sizeof ... ( ParamNames ) <= ParameterTypesNumber >::type * = nullptr >
 	static std::array < std::string, ParameterTypesNumber > generateNames ( ParamNames ... paramNames ) {
 		std::array < std::string, ParameterTypesNumber > parameterNames = { { paramNames ... } };
@@ -20,59 +22,61 @@ protected:
 };
 
 template < class Algorithm, class ReturnType, class ... ParameterTypes >
-class AbstractRegister : public AlgoRegister {
-	abstraction::AlgorithmCategories::AlgorithmCategory m_category;
-
+class AbstractRegister : public ext::Register < void > {
 	registration::NormalizationRegister < ReturnType > normalize;
 
+	abstraction::AlgorithmCategories::AlgorithmCategory m_category;
+
 public:
 	template < class ... ParamNames >
-	AbstractRegister ( ReturnType ( * callback ) ( ParameterTypes ... ), abstraction::AlgorithmCategories::AlgorithmCategory category, ParamNames ... paramNames ) : m_category ( category ) {
-		std::array < std::string, sizeof ... ( ParameterTypes ) > parameterNames = generateNames < sizeof ... ( ParameterTypes ) > ( paramNames ... );
+	AbstractRegister ( ReturnType ( * callback ) ( ParameterTypes ... ), abstraction::AlgorithmCategories::AlgorithmCategory category, ParamNames ... paramNames ) : ext::Register < void > ( [=] ( ) {
+				std::array < std::string, sizeof ... ( ParameterTypes ) > parameterNames = AlgoRegisterHelper::generateNames < sizeof ... ( ParameterTypes ) > ( paramNames ... );
 
-		abstraction::AlgorithmRegistry::registerAlgorithm < Algorithm, ReturnType, ParameterTypes ... > ( callback, category, std::move ( parameterNames ) );
+				abstraction::AlgorithmRegistry::registerAlgorithm < Algorithm, ReturnType, ParameterTypes ... > ( callback, category, std::move ( parameterNames ) );
+			}, [=] ( ) {
+				abstraction::AlgorithmRegistry::unregisterAlgorithm < Algorithm, ParameterTypes ... > ( category );
+			} ), m_category ( category ) {
 	}
 
 	template < class ... ParamNames >
 	AbstractRegister ( ReturnType ( * callback ) ( ParameterTypes ... ) ) : AbstractRegister ( callback, abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT ) {
 	}
 
-	~AbstractRegister ( ) {
-		abstraction::AlgorithmRegistry::unregisterAlgorithm < Algorithm, ParameterTypes ... > ( m_category );
+	AbstractRegister ( AbstractRegister && ) = default;
+
+	AbstractRegister && setDocumentation ( std::string documentation ) && {
+		abstraction::AlgorithmRegistry::setDocumentationOfAlgorithm < Algorithm, ParameterTypes ... > ( m_category, std::move ( documentation ) );
+		return std::move ( * this );
 	}
 };
 
 template < class Algorithm, class ReturnType, class ... ParameterTypes >
-class WrapperRegister : public AlgoRegister {
+class WrapperRegister : public ext::Register < void > {
 public:
 	template < class ... ParamNames >
-	WrapperRegister ( std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( ParameterTypes ... ), ParamNames ... paramNames ) {
-		std::array < std::string, sizeof ... ( ParameterTypes ) > parameterNames = generateNames < sizeof ... ( ParameterTypes ) > ( paramNames ... );
-
-		abstraction::AlgorithmRegistry::registerWrapper < Algorithm, ReturnType, ParameterTypes ... > ( callback, std::move ( parameterNames ) );
-	}
+	WrapperRegister ( std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( ParameterTypes ... ), ParamNames ... paramNames ) : ext::Register < void > ( [=] ( ) {
+				std::array < std::string, sizeof ... ( ParameterTypes ) > parameterNames = AlgoRegisterHelper::generateNames < sizeof ... ( ParameterTypes ) > ( paramNames ... );
 
-	~WrapperRegister ( ) {
-		abstraction::AlgorithmRegistry::unregisterWrapper < Algorithm, ParameterTypes ... > ( );
+				abstraction::AlgorithmRegistry::registerWrapper < Algorithm, ReturnType, ParameterTypes ... > ( callback, std::move ( parameterNames ) );
+			}, [=] ( ) {
+				abstraction::AlgorithmRegistry::unregisterWrapper < Algorithm, ParameterTypes ... > ( );
+			} ) {
 	}
 };
 
 template < class Algorithm, class ReturnType, class ObjectType, class ... ParameterTypes >
-class MethodRegister : public AlgoRegister {
-	std::string m_methodName;
-
+class MethodRegister : public ext::Register < void > {
 	registration::NormalizationRegister < ReturnType > normalize;
 
 public:
 	template < class ... ParamNames >
-	MethodRegister ( ReturnType ( ObjectType::* callback ) ( ParameterTypes ... ), std::string methodName, ParamNames ... paramNames ) : m_methodName ( methodName ) {
-		std::array < std::string, sizeof ... ( ParameterTypes ) > parameterNames = generateNames < sizeof ... ( ParameterTypes ) > ( paramNames ... );
-
-		abstraction::AlgorithmRegistry::registerMethod < Algorithm > ( callback, methodName, std::move ( parameterNames ) );
-	}
+	MethodRegister ( ReturnType ( ObjectType::* callback ) ( ParameterTypes ... ), std::string methodName, ParamNames ... paramNames ) : ext::Register < void > ( [=] ( ) {
+				std::array < std::string, sizeof ... ( ParameterTypes ) > parameterNames = AlgoRegisterHelper::generateNames < sizeof ... ( ParameterTypes ) > ( paramNames ... );
 
-	~MethodRegister ( ) {
-		abstraction::AlgorithmRegistry::unregisterMethod < Algorithm, ObjectType, ParameterTypes ... > ( m_methodName );
+				abstraction::AlgorithmRegistry::registerMethod < Algorithm > ( callback, methodName, std::move ( parameterNames ) );
+			}, [=] ( ) {
+				abstraction::AlgorithmRegistry::unregisterMethod < Algorithm, ObjectType, ParameterTypes ... > ( methodName );
+			} ) {
 	}
 
 };
diff --git a/alib2abstraction/src/registration/NormalizationRegistration.hpp b/alib2abstraction/src/registration/NormalizationRegistration.hpp
index b4806357f5..f430f39244 100644
--- a/alib2abstraction/src/registration/NormalizationRegistration.hpp
+++ b/alib2abstraction/src/registration/NormalizationRegistration.hpp
@@ -3,34 +3,22 @@
 
 #include <registry/NormalizeRegistry.hpp>
 
+#include <alib/registration>
+
 namespace registration {
 
 template < class ReturnType, typename enable = void >
 class NormalizationRegister {
-public:
-	NormalizationRegister ( ) {
-	}
-
-	bool requireNormalization ( ) const {
-		return false;
-	}
 };
 
 template < class ReturnType >
-class NormalizationRegister < ReturnType, typename std::enable_if < ! std::is_same < ReturnType, core::normalizationResult < ReturnType > >::value >::type > {
-	std::list < std::unique_ptr < abstraction::NormalizeRegistry::Entry > >::const_iterator iter;
-
+class NormalizationRegister < ReturnType, typename std::enable_if < ! std::is_same < ReturnType, core::normalizationResult < ReturnType > >::value >::type > : public ext::Register < std::list < std::unique_ptr < abstraction::NormalizeRegistry::Entry > >::const_iterator > {
 public:
-	NormalizationRegister ( ) {
-		iter = abstraction::NormalizeRegistry::registerNormalize < ReturnType > ( );
-	}
-
-	~NormalizationRegister ( ) {
-		abstraction::NormalizeRegistry::unregisterNormalize < ReturnType > ( iter );
-	}
-
-	bool requireNormalization ( ) const {
-		return true;
+	NormalizationRegister ( ) : ext::Register < std::list < std::unique_ptr < abstraction::NormalizeRegistry::Entry > >::const_iterator > ( [=] ( ) {
+				return abstraction::NormalizeRegistry::registerNormalize < ReturnType > ( );
+			}, [=] ( std::list < std::unique_ptr < abstraction::NormalizeRegistry::Entry > >::const_iterator iter ) {
+				abstraction::NormalizeRegistry::unregisterNormalize < ReturnType > ( iter );
+			} ) {
 	}
 };
 
diff --git a/alib2algo/src/automaton/determinize/Determinize.cpp b/alib2algo/src/automaton/determinize/Determinize.cpp
index 809eed6fa3..30f5fbe804 100644
--- a/alib2algo/src/automaton/determinize/Determinize.cpp
+++ b/alib2algo/src/automaton/determinize/Determinize.cpp
@@ -23,7 +23,7 @@ namespace automaton {
 
 namespace determinize {
 
-auto DeterminizeDFA = registration::AbstractRegister < Determinize, automaton::DFA < >, const automaton::DFA < > & > ( Determinize::determinize );
+auto DeterminizeDFA = registration::AbstractRegister < Determinize, automaton::DFA < >, const automaton::DFA < > & > ( Determinize::determinize ).setDocumentation ( "Yay" );
 
 auto DeterminizeNFA = registration::AbstractRegister < Determinize, automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > >, const automaton::NFA < > & > ( Determinize::determinize );
 
diff --git a/alib2cli/src/command/OverloadsIntrospectionCommand.h b/alib2cli/src/command/OverloadsIntrospectionCommand.h
index 45d6f61e29..46adddaf17 100644
--- a/alib2cli/src/command/OverloadsIntrospectionCommand.h
+++ b/alib2cli/src/command/OverloadsIntrospectionCommand.h
@@ -61,7 +61,7 @@ public:
 			}
 			common::Streams::out << " )" << std::endl << std::endl;
 
-			common::Streams::out << std::get < 3 > ( overload ) << std::endl << std::endl;
+			common::Streams::out << std::get < 4 > ( overload ) << std::endl << std::endl;
 		}
 
 		return Command::Result::OK;
diff --git a/alib2std/src/extensions/registration.hpp b/alib2std/src/extensions/registration.hpp
index 94f816cf23..378540c916 100644
--- a/alib2std/src/extensions/registration.hpp
+++ b/alib2std/src/extensions/registration.hpp
@@ -28,7 +28,38 @@
 
 namespace ext {
 
+template < class T >
 class Register {
+	T data;
+
+	std::function < void ( T ) > m_finish;
+public:
+	template < class InitCallback, class FinalizeCallback >
+	Register ( InitCallback init, FinalizeCallback finish ) : m_finish ( finish ) {
+		data = init ( );
+	}
+
+	template < class InitCallback >
+	Register ( InitCallback init ) : Register ( init, [] ( T ) { } ) {
+	}
+
+	Register ( const Register & ) = delete;
+
+	Register ( Register && other ) : data ( std::move ( other.data ) ), m_finish ( other.m_finish ) {
+		other.m_finish = [] ( T ) { };
+	}
+
+	Register & operator = ( const Register & ) = delete;
+
+	Register & operator = ( Register && other ) = delete;
+
+	~Register ( ) {
+		m_finish ( data );
+	}
+};
+
+template < >
+class Register < void > {
 	std::function < void ( ) > m_finish;
 public:
 	template < class InitCallback, class FinalizeCallback >
@@ -37,9 +68,19 @@ public:
 	}
 
 	template < class InitCallback >
-	Register ( InitCallback init ) : Register ( init, [](){} ) {
+	Register ( InitCallback init ) : Register ( init, [] ( ) { } ) {
 	}
 
+	Register ( const Register & ) = delete;
+
+	Register ( Register && other ) : m_finish ( other.m_finish ) {
+		other.m_finish = [] ( ) { };
+	}
+
+	Register & operator = ( const Register & ) = delete;
+
+	Register & operator = ( Register && other ) = delete;
+
 	~Register ( ) {
 		m_finish ( );
 	}
diff --git a/aql2/src/prompt/ReadlinePromptCompletion.cpp b/aql2/src/prompt/ReadlinePromptCompletion.cpp
index 873f2b5476..a9c3d08d1e 100644
--- a/aql2/src/prompt/ReadlinePromptCompletion.cpp
+++ b/aql2/src/prompt/ReadlinePromptCompletion.cpp
@@ -9,7 +9,7 @@
 
 #include "ReadlinePromptCompletion.h"
 
-static ext::Register instance ( [ ] ( ) {
+static ext::Register < void > instance ( [ ] ( ) {
 		// register readline completion function, pass environment
 		rl_attempted_completion_function = ReadlinePromptCompletion::readline_completion;
 	} );
-- 
GitLab