From 320ed6356536989234a517b5348e9a34705b167a Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 3 Apr 2019 09:01:33 +0200
Subject: [PATCH] add and test use automata detection traits

---
 alib2algo/src/automaton/convert/ToGrammar.h   | 24 ++----
 .../src/automaton/convert/ToGrammarLeftRG.h   | 76 +++++--------------
 alib2data/src/automaton/FSM/CompactDFA.h      | 27 +++++++
 alib2data/src/automaton/FSM/CompactNFA.h      | 27 +++++++
 alib2data/src/automaton/FSM/DFA.h             | 27 +++++++
 alib2data/src/automaton/FSM/EpsilonNFA.h      | 27 +++++++
 alib2data/src/automaton/FSM/ExtendedNFA.h     | 29 ++++++-
 .../FSM/MultiInitialStateEpsilonNFA.h         | 27 +++++++
 .../src/automaton/FSM/MultiInitialStateNFA.h  | 27 +++++++
 alib2data/src/automaton/FSM/NFA.h             | 27 +++++++
 alib2std/src/extensions/type_traits.hpp       |  5 ++
 11 files changed, 246 insertions(+), 77 deletions(-)

diff --git a/alib2algo/src/automaton/convert/ToGrammar.h b/alib2algo/src/automaton/convert/ToGrammar.h
index 209b10a145..d0cf5be25c 100644
--- a/alib2algo/src/automaton/convert/ToGrammar.h
+++ b/alib2algo/src/automaton/convert/ToGrammar.h
@@ -24,9 +24,10 @@
 #ifndef _AUTOMATON_TO_GRAMMAR_H__
 #define _AUTOMATON_TO_GRAMMAR_H__
 
-#include <grammar/Regular/LeftRG.h>
+#include <grammar/Regular/RightRG.h>
 #include <automaton/FSM/NFA.h>
 #include <automaton/FSM/DFA.h>
+#include <automaton/Automaton.h>
 #include "ToGrammarRightRG.h"
 
 namespace automaton {
@@ -43,30 +44,19 @@ public:
 	/**
 	 * Performs the conversion (@sa ToGrammarRightRG::convert).
 	 *
-	 * \tparam SymbolType Type for symbols.
-	 * \tparam StateType Type for states.
+	 * \tparam T the converted automaton
 	 *
 	 * \param automaton the automaton to convert
 	 *
 	 * \return right regular grammar equivalent to the input @p automaton
 	 */
-	template < class SymbolType, class StateType >
-	static grammar::RightRG < SymbolType, StateType > convert(const automaton::NFA < SymbolType, StateType > & automaton);
+	template < class T >
+	static ext::require < isDFA < T > || isNFA < T >, grammar::RightRG < typename automaton::SymbolTypeOfAutomaton < T >, typename automaton::StateTypeOfAutomaton < T > > > convert ( const T & automaton );
 
-	/**
-	 * \overload
-	 */
-	template < class SymbolType, class StateType >
-	static grammar::RightRG < SymbolType, StateType > convert(const automaton::DFA < SymbolType, StateType > & automaton);
 };
 
-template < class SymbolType, class StateType >
-grammar::RightRG < SymbolType, StateType > ToGrammar::convert(const automaton::NFA < SymbolType, StateType > & automaton) {
-	return ToGrammarRightRG::convert ( automaton );
-}
-
-template < class SymbolType, class StateType >
-grammar::RightRG < SymbolType, StateType > ToGrammar::convert(const automaton::DFA < SymbolType, StateType > & automaton) {
+template < class T >
+ext::require < isDFA < T > || isNFA < T >, grammar::RightRG < typename automaton::SymbolTypeOfAutomaton < T >, typename automaton::StateTypeOfAutomaton < T > > > ToGrammar::convert ( const T & automaton ) {
 	return ToGrammarRightRG::convert ( automaton );
 }
 
diff --git a/alib2algo/src/automaton/convert/ToGrammarLeftRG.h b/alib2algo/src/automaton/convert/ToGrammarLeftRG.h
index 52b78b2a2e..33f5bc3ad2 100644
--- a/alib2algo/src/automaton/convert/ToGrammarLeftRG.h
+++ b/alib2algo/src/automaton/convert/ToGrammarLeftRG.h
@@ -28,6 +28,7 @@
 #include <grammar/Regular/LeftRG.h>
 #include <automaton/FSM/NFA.h>
 #include <automaton/FSM/DFA.h>
+#include <automaton/Automaton.h>
 
 #include <alib/map>
 #include <common/createUnique.hpp>
@@ -46,45 +47,42 @@ public:
 	/**
 	 * Performs the conversion of the finite automaton to left regular grammar.
 	 *
-	 * \tparam SymbolType the type of input/terminal symbols of automaton and the resulting grammar
-	 * \tparam StateType the type of states of the automaton and nonterminal symbols of the resulting grammar
+	 * \tparam T the converted automaton
 	 *
 	 * \param automaton a finite automaton to convert
 	 *
 	 * \return left regular grammar equivalent to the source @p automaton.
 	 */
-	template < class SymbolType, class StateType >
-	static grammar::LeftRG < SymbolType, StateType > convert(const automaton::NFA < SymbolType, StateType > & automaton);
+	template < class T >
+	static ext::require < isDFA < T > || isNFA < T >, grammar::LeftRG < typename automaton::SymbolTypeOfAutomaton < T >, typename automaton::StateTypeOfAutomaton < T > > > convert ( const T & automaton );
 
-	/**
-	 * \overload
-	 */
-	template < class SymbolType, class StateType >
-	static grammar::LeftRG < SymbolType, StateType > convert(const automaton::DFA < SymbolType, StateType > & automaton);
 };
 
-template < class SymbolType, class StateType >
-grammar::LeftRG < SymbolType, StateType > ToGrammarLeftRG::convert(const automaton::NFA < SymbolType, StateType > & automaton) {
+template < class T >
+ext::require < isDFA < T > || isNFA < T >, grammar::LeftRG < typename automaton::SymbolTypeOfAutomaton < T >, typename automaton::StateTypeOfAutomaton < T > > > ToGrammarLeftRG::convert ( const T & automaton ) {
+	using SymbolType = automaton::SymbolTypeOfAutomaton < T >;
+	using StateType = automaton::StateTypeOfAutomaton < T >;
+
 	// step 2
 	grammar::LeftRG < SymbolType, StateType > grammar(alphabet::InitialSymbol::instance < StateType > ( ) );
 
 	// step 1
-	grammar.setTerminalAlphabet(automaton.getInputAlphabet());
+	grammar.setTerminalAlphabet ( automaton.getInputAlphabet ( ) );
 
 	for ( const auto & state : automaton.getStates ( ) ) {
 		grammar.addNonterminalSymbol ( state );
 	}
 
 	// step 3 - create set of P in G
-	for(const auto& transition : automaton.getTransitions()) {
-		const StateType& from = transition.first.first;
-		const SymbolType& input = transition.first.second;
-		const StateType& to = transition.second;
+	for ( const auto & transition : automaton.getTransitions ( ) ) {
+		const StateType & from = transition.first.first;
+		const SymbolType & input = transition.first.second;
+		const StateType & to = transition.second;
 
 		// 3a
 		grammar.addRule ( to, ext::make_pair ( from, input ) );
 
-		if ( automaton.getFinalStates ( ).count ( to ) > 0)
+		if ( automaton.getFinalStates ( ).count ( to ) > 0 )
 			grammar.addRule ( grammar.getInitialSymbol ( ), ext::make_pair ( from, input ) );
 
 
@@ -96,48 +94,8 @@ grammar::LeftRG < SymbolType, StateType > ToGrammarLeftRG::convert(const automat
 		}
 	}
 
-	if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
-		grammar.setGeneratesEpsilon(true);
-
-	return grammar;
-}
-
-template < class SymbolType, class StateType >
-grammar::LeftRG < SymbolType, StateType > ToGrammarLeftRG::convert ( const automaton::DFA < SymbolType, StateType > & automaton ) {
-	// step 2
-	grammar::LeftRG < SymbolType, StateType > grammar(alphabet::InitialSymbol::instance < StateType > ( ) );
-
-	// step 1
-	grammar.setTerminalAlphabet(automaton.getInputAlphabet());
-
-	for ( const auto & state : automaton.getStates ( ) ) {
-		grammar.addNonterminalSymbol ( state );
-	}
-
-	// step 3 - create set of P in G
-	for(const auto& transition : automaton.getTransitions()) {
-		const StateType& from = transition.first.first;
-		const SymbolType& input = transition.first.second;
-		const StateType& to = transition.second;
-
-		// 3a
-		grammar.addRule(to, ext::make_pair(from, input));
-
-		if(automaton.getFinalStates().count(to) > 0)
-			grammar.addRule(grammar.getInitialSymbol(), ext::make_pair(from, input));
-
-
-		if(automaton.getInitialState() == from)
-		{
-			grammar.addRule(to, input);
-
-			if(automaton.getFinalStates().count(to) > 0)
-				grammar.addRule(grammar.getInitialSymbol(), input);
-		}
-	}
-
-	if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
-		grammar.setGeneratesEpsilon(true);
+	if ( automaton.getFinalStates ( ).count ( automaton.getInitialState ( ) ) > 0 )
+		grammar.setGeneratesEpsilon ( true );
 
 	return grammar;
 }
diff --git a/alib2data/src/automaton/FSM/CompactDFA.h b/alib2data/src/automaton/FSM/CompactDFA.h
index af64f2ef73..e23cfc24b9 100644
--- a/alib2data/src/automaton/FSM/CompactDFA.h
+++ b/alib2data/src/automaton/FSM/CompactDFA.h
@@ -383,6 +383,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not CompactDFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isCompactDFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not CompactDFA. Derived from std::true_type.
+ *
+ * Specialisation for CompactDFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isCompactDFA_impl < CompactDFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is CompactDFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isCompactDFA = isCompactDFA_impl < T > { };
+
 template < class SymbolType, class StateType >
 CompactDFA < SymbolType, StateType >::CompactDFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ) : core::Components < CompactDFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
 }
diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h
index 504513af1e..f119086212 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.h
+++ b/alib2data/src/automaton/FSM/CompactNFA.h
@@ -429,6 +429,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not CompactNFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isCompactNFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not CompactNFA. Derived from std::true_type.
+ *
+ * Specialisation for CompactNFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isCompactNFA_impl < CompactNFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is CompactNFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isCompactNFA = isCompactNFA_impl < T > { };
+
 template < class SymbolType, class StateType >
 CompactNFA < SymbolType, StateType >::CompactNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ) : core::Components < CompactNFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
 }
diff --git a/alib2data/src/automaton/FSM/DFA.h b/alib2data/src/automaton/FSM/DFA.h
index df3dda5ad8..fce57c8a9d 100644
--- a/alib2data/src/automaton/FSM/DFA.h
+++ b/alib2data/src/automaton/FSM/DFA.h
@@ -384,6 +384,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not DFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isDFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not DFA. Derived from std::true_type.
+ *
+ * Specialisation for DFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isDFA_impl < DFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is DFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isDFA = isDFA_impl < T > { };
+
 template<class SymbolType, class StateType >
 DFA<SymbolType, StateType>::DFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ) : core::Components < DFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
 }
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.h b/alib2data/src/automaton/FSM/EpsilonNFA.h
index 044887ac99..1f160d17bb 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.h
@@ -535,6 +535,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not EpsilonNFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isEpsilonNFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not EpsilonNFA. Derived from std::true_type.
+ *
+ * Specialisation for EpsilonNFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isEpsilonNFA_impl < EpsilonNFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is EpsilonNFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isEpsilonNFA = isEpsilonNFA_impl < T > { };
+
 template<class SymbolType, class EpsilonType, class StateType >
 EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ) : core::Components < EpsilonNFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
 }
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h
index 5cd619ad25..d9434a9075 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.h
@@ -431,6 +431,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not ExtendedNFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isExtendedNFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not ExtendedNFA. Derived from std::true_type.
+ *
+ * Specialisation for ExtendedNFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isExtendedNFA_impl < ExtendedNFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is ExtendedNFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isExtendedNFA = isExtendedNFA_impl < T > { };
+
 template<class SymbolType, class StateType >
 ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ) : core::Components < ExtendedNFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
 }
@@ -451,6 +478,7 @@ ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const CompactNFA < SymbolTy
 		transitions.insert ( key, transition.second );
 	}
 }
+
 template < class SymbolType, class StateType >
 template < class EpsilonType >
 ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : ExtendedNFA ( other.getStates ( ) + ext::set < StateType > { common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ) }, other.getInputAlphabet ( ), common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ), other.getFinalStates ( ) ) {
@@ -469,7 +497,6 @@ ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const MultiInitialStateEpsi
 		transitions.insert ( key, to );
 }
 
-
 template < class SymbolType, class StateType >
 template < class EpsilonType >
 ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const EpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
index e58d115392..e45830d498 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
@@ -558,6 +558,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not MultiInitialStateEpsilonNFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isMultiInitialStateEpsilonNFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not MultiInitialStateEpsilonNFA. Derived from std::true_type.
+ *
+ * Specialisation for MultiInitialStateEpsilonNFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isMultiInitialStateEpsilonNFA_impl < MultiInitialStateEpsilonNFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is MultiInitialStateEpsilonNFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isMultiInitialStateEpsilonNFA = isMultiInitialStateEpsilonNFA_impl < T > { };
+
 template<class SymbolType, class EpsilonType, class StateType >
 MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, ext::set < StateType > initialStates, ext::set < StateType > finalStates ) : core::Components < MultiInitialStateEpsilonNFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, InitialStates, FinalStates > > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( initialStates ), std::move ( finalStates ) ) {
 }
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
index 9025e396c2..2833d28176 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
@@ -436,6 +436,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not MultiInitialStateNFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isMultiInitialStateNFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not MultiInitialStateNFA. Derived from std::true_type.
+ *
+ * Specialisation for MultiInitialStateNFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isMultiInitialStateNFA_impl < MultiInitialStateNFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is MultiInitialStateNFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isMultiInitialStateNFA = isMultiInitialStateNFA_impl < T > { };
+
 template < class SymbolType, class StateType >
 MultiInitialStateNFA < SymbolType, StateType >::MultiInitialStateNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, ext::set < StateType > initialStates, ext::set < StateType > finalStates ) : core::Components < MultiInitialStateNFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, InitialStates, FinalStates > > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( initialStates ), std::move ( finalStates ) ) {
 }
diff --git a/alib2data/src/automaton/FSM/NFA.h b/alib2data/src/automaton/FSM/NFA.h
index 769050483b..ab8a87d187 100644
--- a/alib2data/src/automaton/FSM/NFA.h
+++ b/alib2data/src/automaton/FSM/NFA.h
@@ -397,6 +397,33 @@ public:
 	explicit operator std::string ( ) const;
 };
 
+/**
+ * Trait to detect whether the type parameter T is or is not NFA. Derived from std::false_type.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+class isNFA_impl : public std::false_type {};
+
+/**
+ * Trait to detect whether the type parameter T is or is not NFA. Derived from std::true_type.
+ *
+ * Specialisation for NFA.
+ *
+ * \tparam SymbolType used for the terminal alphabet of the automaton
+ * \tparam StateType used for the terminal alphabet of the automaton
+ */
+template < class SymbolType, class StateType >
+class isNFA_impl < NFA < SymbolType, StateType > > : public std::true_type {};
+
+/**
+ * Constexpr true if the type parameter T is NFA, false otherwise.
+ *
+ * \tparam T the tested type parameter
+ */
+template < class T >
+constexpr bool isNFA = isNFA_impl < T > { };
+
 template<class SymbolType, class StateType >
 NFA < SymbolType, StateType >::NFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ) : core::Components < NFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
 }
diff --git a/alib2std/src/extensions/type_traits.hpp b/alib2std/src/extensions/type_traits.hpp
index 12756c1aeb..a36d973597 100644
--- a/alib2std/src/extensions/type_traits.hpp
+++ b/alib2std/src/extensions/type_traits.hpp
@@ -133,6 +133,11 @@ namespace ext {
 	template < typename T, typename ... Ts >
 	struct is_in < T, T, Ts ... > : std::true_type { };
 
+// ----------------------------------------------------------------------------------------------------
+
+	template < bool value, typename type = int >
+	using require = typename std::enable_if < value, type >::type;
+
 } /* namespace ext */
 
 #endif /* __TYPE_TRAITS_HPP_ */
-- 
GitLab