diff --git a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp
index 35ebd2a4526b77d9da7efc704c1490e69ebaccb7..012ea0be36b88882921395d04670b6c5af300239 100644
--- a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp
+++ b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp
@@ -16,71 +16,8 @@ automaton::Automaton AutomataIntersectionCartesianProduct::intersection(const au
 	return dispatch(first.getData(), second.getData());
 }
 
-automaton::DFA<> AutomataIntersectionCartesianProduct::intersection(const automaton::DFA<>& first, const automaton::DFA<>& second) {
-	DefaultStateType q0(first.getInitialState(), second.getInitialState());
-	automaton::DFA<> res(q0);
-
-	for(const auto& a : first.getInputAlphabet())
-		res.addInputSymbol(a);
-	for(const auto& a : second.getInputAlphabet())
-		res.addInputSymbol(a);
-
-	for(const auto& p : first.getStates())
-		for(const auto& q : second.getStates())
-			res.addState(DefaultStateType(p, q));
-
-	for(const auto& p : first.getFinalStates())
-		for(const auto& q : second.getFinalStates())
-			res.addFinalState(DefaultStateType(p, q));
-
-	for(const auto& state : res.getStates()) {
-		const DefaultStateType& label_p = static_cast<const DefaultStatesPairType&>(state.getData()).first;
-		const DefaultStateType& label_q = static_cast<const DefaultStatesPairType&>(state.getData()).second;
-
-		for(const auto& tp : first.getTransitionsFromState(DefaultStateType(label_p)))
-			for(const auto& tq : second.getTransitionsFromState(DefaultStateType(label_q)))
-				if(tp.first.second == tq.first.second)
-					res.addTransition(state, tp.first.second, DefaultStateType(tp.second, tq.second));
-	}
-
-	return res;
-}
-
-auto AutomataIntersectionCartesianProductDFA = AutomataIntersectionCartesianProduct::RegistratorWrapper<automaton::DFA<>, automaton::DFA<>>(AutomataIntersectionCartesianProduct::intersection);
-
-automaton::NFA < > AutomataIntersectionCartesianProduct::intersection(const automaton::NFA < > & first, const automaton::NFA < > & second) {
-	DefaultStateType q0(first.getInitialState(), second.getInitialState());
-	automaton::NFA < > res(q0);
-
-	for(const auto& a : first.getInputAlphabet())
-		res.addInputSymbol(a);
-	for(const auto& a : second.getInputAlphabet())
-		res.addInputSymbol(a);
-
-	for(const auto& p : first.getStates())
-		for(const auto& q : second.getStates())
-			res.addState(DefaultStateType(p, q));
-
-	for(const auto& p : first.getFinalStates())
-		for(const auto& q : second.getFinalStates())
-			res.addFinalState(DefaultStateType(p, q));
-
-	for(const auto& state : res.getStates()) {
-		const DefaultStateType& label_p = static_cast<const DefaultStatesPairType&>(state.getData()).first;
-		const DefaultStateType& label_q = static_cast<const DefaultStatesPairType&>(state.getData()).second;
-
-		for(const auto& tp : first.getTransitionsFromState(DefaultStateType(label_p)))
-			for(const auto& tq : second.getTransitionsFromState(DefaultStateType(label_q)))
-				if(tp.first.second == tq.first.second)
-					for(const auto& p : tp.second)
-						for(const auto& q : tq.second)
-							res.addTransition(state, tp.first.second, DefaultStateType(p, q));
-	}
-
-	return res;
-}
-
-auto AutomataIntersectionCartesianProductNFA = AutomataIntersectionCartesianProduct::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(AutomataIntersectionCartesianProduct::intersection);
+auto AutomataIntersectionCartesianProductDFA = AutomataIntersectionCartesianProduct::RegistratorWrapper<automaton::DFA < DefaultSymbolType, std::pair < DefaultStateType, DefaultStateType > >, automaton::DFA < > >(AutomataIntersectionCartesianProduct::intersection);
+auto AutomataIntersectionCartesianProductNFA = AutomataIntersectionCartesianProduct::RegistratorWrapper<automaton::NFA < DefaultSymbolType, std::pair < DefaultStateType, DefaultStateType > >, automaton::NFA < > >(AutomataIntersectionCartesianProduct::intersection);
 
 } /* namespace transform */
 
diff --git a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h
index 7c07ff5d2162c3a21d0a8c1da362e202ec27f735..f9e48a5d42780bc157161b359288bb1724f0e301 100644
--- a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h
+++ b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h
@@ -24,10 +24,68 @@ class AutomataIntersectionCartesianProduct : public std::PromotingDoubleDispatch
 public:
 	static automaton::Automaton intersection(const automaton::Automaton& first, const automaton::Automaton& second);
 
-	static automaton::NFA < > intersection(const automaton::NFA < > & first, const automaton::NFA < > & second);
-	static automaton::DFA<> intersection(const automaton::DFA<>& first, const automaton::DFA<>& second);
+	template < class SymbolType, class StateType1, class StateType2 >
+	static automaton::NFA < SymbolType, std::pair < StateType1, StateType2 > > intersection(const automaton::NFA < SymbolType, StateType1 > & first, const automaton::NFA < SymbolType, StateType2 > & second);
+	template < class SymbolType, class StateType1, class StateType2 >
+	static automaton::DFA < SymbolType, std::pair < StateType1, StateType2 > > intersection(const automaton::DFA < SymbolType, StateType1 > & first, const automaton::DFA < SymbolType, StateType2 > & second);
 };
 
+template < class SymbolType, class StateType1, class StateType2 >
+automaton::DFA < SymbolType, std::pair < StateType1, StateType2 > > AutomataIntersectionCartesianProduct::intersection(const automaton::DFA < SymbolType, StateType1 > & first, const automaton::DFA < SymbolType, StateType2 > & second) {
+	std::pair < StateType1, StateType2 > q0 ( first.getInitialState ( ), second.getInitialState ( ) );
+	automaton::DFA < SymbolType, std::pair < StateType1, StateType2 > > res(q0);
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& p : first.getStates())
+		for(const auto& q : second.getStates())
+			res.addState ( std::make_pair ( p, q ) );
+
+	for(const auto& p : first.getFinalStates())
+		for(const auto& q : second.getFinalStates())
+			res.addFinalState ( std::make_pair ( p, q ) );
+
+	for(const std::pair < StateType1, StateType2 > & state : res.getStates ( ) )
+		for(const auto & tp : first.getTransitionsFromState ( state.first ) )
+			for(const auto & tq : second.getTransitionsFromState ( state.second ) )
+				if(tp.first.second == tq.first.second)
+					res.addTransition ( state, tp.first.second, std::make_pair ( tp.second, tq.second ) );
+
+	return res;
+}
+
+template < class SymbolType, class StateType1, class StateType2 >
+automaton::NFA < SymbolType, std::pair < StateType1, StateType2 > > AutomataIntersectionCartesianProduct::intersection(const automaton::NFA < SymbolType, StateType1 > & first, const automaton::NFA < SymbolType, StateType2 > & second) {
+	std::pair < StateType1, StateType2 > q0 ( first.getInitialState ( ), second.getInitialState ( ) );
+	automaton::NFA < SymbolType, std::pair < StateType1, StateType2 > > res ( q0 );
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& p : first.getStates())
+		for(const auto& q : second.getStates())
+			res.addState ( std::make_pair ( p, q ) );
+
+	for(const auto& p : first.getFinalStates())
+		for(const auto& q : second.getFinalStates())
+			res.addFinalState ( std::make_pair ( p, q ) );
+
+	for(const std::pair < StateType1, StateType2 > & state : res.getStates ( ) )
+		for(const auto & tp : first.getTransitionsFromState ( state.first ) )
+			for(const auto & tq : second.getTransitionsFromState ( state.second ) )
+				if(tp.first.second == tq.first.second)
+					for(const auto & p : tp.second)
+						for(const auto & q : tq.second)
+							res.addTransition ( state, tp.first.second, std::make_pair ( p, q ) );
+
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */