diff --git a/aconvert2/src/aconvert.cpp b/aconvert2/src/aconvert.cpp
index 25eeebaba4729361a8e6b2b366c8eb939a260d46..87b23b891cf8f60971c395e53ff2c84a9ea70c6f 100644
--- a/aconvert2/src/aconvert.cpp
+++ b/aconvert2/src/aconvert.cpp
@@ -101,15 +101,15 @@ int main ( int argc, char * argv[] ) {
 
 		std::string algoCli;
 		if ( automaton_from_string.getValue ( ) )
-			algoCli = "execute string::Parse automaton::Automaton ^ $input > $output";
+			algoCli = "execute string::Parse @ automaton::Automaton ^ $input > $output";
 		else if ( grammar_from_string.getValue ( ) )
-			algoCli = "execute string::Parse grammar::Grammar ^ $input > $output";
+			algoCli = "execute string::Parse @ grammar::Grammar ^ $input > $output";
 		else if ( regexp_from_string.getValue ( ) )
-			algoCli = "execute string::Parse regexp::RegExp ^ $input > $output";
+			algoCli = "execute string::Parse @ regexp::RegExp ^ $input > $output";
 		else if ( string_from_string.getValue ( ) )
-			algoCli = "execute string::Parse string::String ^ $input > $output";
+			algoCli = "execute string::Parse @ string::String ^ $input > $output";
 		else if ( tree_from_string.getValue ( ) )
-			algoCli = "execute string::Parse tree::Tree ^ $input > $output";
+			algoCli = "execute string::Parse @ tree::Tree ^ $input > $output";
 		else if ( automaton_to_string.getValue ( ) )
 			algoCli = "execute string::Compose $input > $output";
 		else if ( automaton_to_dot.getValue ( ) )
diff --git a/aintrospection2/src/aintrospection.cpp b/aintrospection2/src/aintrospection.cpp
index 971a550f8bd7bad9af1570ed7be906d0b86772d1..5382de8957946564618e022137067984c53ae840 100644
--- a/aintrospection2/src/aintrospection.cpp
+++ b/aintrospection2/src/aintrospection.cpp
@@ -95,13 +95,20 @@ int main ( int argc, char * argv[] ) {
 			}
 			tokens.emplace_back("Casts", sax::Token::TokenType::END_ELEMENT);
 			tokens.emplace_back("Algorithms", sax::Token::TokenType::START_ELEMENT);
-			for ( const std::string & algo : abstraction::Registry::listAlgorithms ( ) ) {
+			for ( const ext::pair < std::string, ext::vector < std::string > > & algo : abstraction::Registry::listAlgorithms ( ) ) {
 				tokens.emplace_back("Algorithm", sax::Token::TokenType::START_ELEMENT);
 				tokens.emplace_back("Name", sax::Token::TokenType::START_ELEMENT);
-				tokens.emplace_back(algo, sax::Token::TokenType::CHARACTER);
+				tokens.emplace_back(algo.first, sax::Token::TokenType::CHARACTER);
 				tokens.emplace_back("Name", sax::Token::TokenType::END_ELEMENT);
+				tokens.emplace_back("TemplateParams", sax::Token::TokenType::START_ELEMENT);
+				for ( const std::string & templateParam : algo.second ) {
+					tokens.emplace_back("TemplateParam", sax::Token::TokenType::START_ELEMENT);
+					tokens.emplace_back(templateParam, sax::Token::TokenType::CHARACTER);
+					tokens.emplace_back("TemplateParam", sax::Token::TokenType::END_ELEMENT);
+				}
+				tokens.emplace_back("TemplateParams", sax::Token::TokenType::END_ELEMENT);
 				tokens.emplace_back("Overloads", sax::Token::TokenType::START_ELEMENT);
-				for ( const ext::tuple < abstraction::AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > & over : abstraction::Registry::listOverloads ( algo ) ) {
+				for ( const ext::tuple < abstraction::AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > & over : abstraction::Registry::listOverloads ( algo.first, algo.second ) ) {
 					tokens.emplace_back("Overload", sax::Token::TokenType::START_ELEMENT);
 					tokens.emplace_back("Category", sax::Token::TokenType::START_ELEMENT);
 					tokens.emplace_back(abstraction::AlgorithmCategories::toString ( std::get < 0 > ( over ) ), sax::Token::TokenType::CHARACTER);
diff --git a/alib2abstraction/src/common/AlgorithmHelper.cpp b/alib2abstraction/src/common/AlgorithmHelper.cpp
index 786834775537d80a79303cc48edc317297fed5a1..af08f9e4db34d0988995c72c274baf2fa5e76e31 100644
--- a/alib2abstraction/src/common/AlgorithmHelper.cpp
+++ b/alib2abstraction/src/common/AlgorithmHelper.cpp
@@ -12,12 +12,12 @@
 
 namespace abstraction {
 
-std::shared_ptr < abstraction::OperationAbstraction > AlgorithmHelper::eval ( const std::string & name, const ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > & params, std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category ) {
+std::shared_ptr < abstraction::OperationAbstraction > AlgorithmHelper::eval ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > & params, std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category ) {
 	ext::vector < std::string > paramTypes;
 	for ( const std::shared_ptr < abstraction::OperationAbstraction > & param : params )
 		paramTypes.push_back ( param->getReturnType ( ) );
 
-	std::shared_ptr < abstraction::OperationAbstraction > algo = abstraction::Registry::getAlgorithmAbstraction ( name, paramTypes, category );
+	std::shared_ptr < abstraction::OperationAbstraction > algo = abstraction::Registry::getAlgorithmAbstraction ( name, templateParams, paramTypes, category );
 
 	unsigned i = 0;
 	ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > casted_params;
diff --git a/alib2abstraction/src/common/AlgorithmHelper.h b/alib2abstraction/src/common/AlgorithmHelper.h
index b924c1b2f840be1d10b3bef047570066aa68c54a..f46556a1fde46b13bd43129235b5f03ce1922fab 100644
--- a/alib2abstraction/src/common/AlgorithmHelper.h
+++ b/alib2abstraction/src/common/AlgorithmHelper.h
@@ -17,7 +17,7 @@ namespace abstraction {
 
 class AlgorithmHelper {
 public:
-	static std::shared_ptr < abstraction::OperationAbstraction > eval ( const std::string & algo, const ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > & params, std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category );
+	static std::shared_ptr < abstraction::OperationAbstraction > eval ( const std::string & algo, const ext::vector < std::string > & templateParams, const ext::vector < std::shared_ptr < abstraction::OperationAbstraction > > & params, std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category );
 
 };
 
diff --git a/alib2abstraction/src/registry/AlgorithmRegistry.cpp b/alib2abstraction/src/registry/AlgorithmRegistry.cpp
index e3cc21da26cd8a5b134a97ce9fa9107679f74616..f4480b9831897734ef0ce896dc961801ba9a5c55 100644
--- a/alib2abstraction/src/registry/AlgorithmRegistry.cpp
+++ b/alib2abstraction/src/registry/AlgorithmRegistry.cpp
@@ -16,8 +16,8 @@ ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier
 	return ext::make_pair ( std::string ( "dynamic return type" ), ext::set < ParamQualifiers::ParamQualifier > { } );
 }
 
-bool AlgorithmRegistry::isRegistered ( const std::string & algorithm, AlgorithmCategories::AlgorithmCategory category, const ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > & params ) {
-	auto & group = getEntries ( ) [ algorithm ];
+bool AlgorithmRegistry::isRegistered ( const std::string & algorithm, const ext::vector < std::string > & templateParams, AlgorithmCategories::AlgorithmCategory category, const ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > & params ) {
+	auto & group = getEntries ( ) [ ext::make_pair ( algorithm, templateParams ) ];
 
 	for ( const ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > & entry : group )
 		if ( std::get < 0 > ( entry ) == category && std::get < 1 > ( entry ) == params )
@@ -26,27 +26,33 @@ bool AlgorithmRegistry::isRegistered ( const std::string & algorithm, AlgorithmC
 	return false;
 }
 
-void AlgorithmRegistry::registerInternal ( std::string algorithm, AlgorithmCategories::AlgorithmCategory category, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params, std::shared_ptr < Entry > value ) {
-	auto & group = getEntries ( ) [ algorithm ];
+void AlgorithmRegistry::registerInternal ( std::string algorithm, ext::vector < std::string > templateParams, AlgorithmCategories::AlgorithmCategory category, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params, std::shared_ptr < Entry > value ) {
+	auto & group = getEntries ( ) [ ext::make_pair ( std::move ( algorithm ), std::move ( templateParams ) ) ];
 
 	ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > entryValue = ext::make_pair ( std::move ( result ), std::move ( value ) );
 	group.push_back ( ext::make_tuple ( category, std::move ( params ), entryValue ) );
 }
 
-std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory ) {
-	auto group = getEntries ( ).find ( name );
+std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::getAbstraction ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory ) {
+	auto group = getEntries ( ).find ( ext::make_pair ( name, templateParams ) );
 	if ( group == getEntries ( ).end ( ) ) {
 		for ( auto iter = getEntries ( ).begin ( ); iter != getEntries ( ).end ( ); ++ iter ) {
-			if ( ext::is_same_type ( name, iter->first ) ) {
+			if ( ext::is_same_type ( name, iter->first.first ) && iter->first.second == templateParams ) {
 				if ( group == getEntries ( ).end ( ) )
 					group = iter;
-				else
+				else if ( templateParams.size ( ) == 0 )
 					throw std::invalid_argument ( "Name " + name + " is ambigous " );
+				else
+					throw std::invalid_argument ( "Templated name " + name + " < " + ext::to_string ( templateParams ) + " > is ambigous " );
 			}
 		}
 	}
-	if ( group == getEntries ( ).end ( ) )
-		throw std::invalid_argument ( "Entry " + name + " not available" );
+	if ( group == getEntries ( ).end ( ) ) {
+		if ( templateParams.size ( ) == 0 )
+			throw std::invalid_argument ( "Entry " + name + " not available" );
+		else
+			throw std::invalid_argument ( "Templated entry " + name + " < " + ext::to_string ( templateParams ) + " > not available" );
+	}
 
 	auto incompatibleLambda = [ ] ( const ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > & compatibility ) {
 		return std::get < 0 > ( compatibility ) == MatchType::INCOMPATIBLE;
@@ -127,38 +133,39 @@ std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::getAbst
 	if ( winner.size ( ) == 1 ) {
 		best = compatibilityData [ * winner.begin ( ) ].second.second;
 	} else if ( winner.size ( ) > 1 ) {
-		std::stringstream ss;
-		ss << paramTypes;
-
-//		throw std::invalid_argument ( "Entry overload " + ss.str ( ) + " ambiguous." ); FIXME make better overload select algorithm
+//		throw std::invalid_argument ( "Entry overload " + ext::to_string ( paramTypes ) + " ambiguous." ); FIXME make better overload select algorithm
 		best = compatibilityData [ * winner.begin ( ) ].second.second;
 
 /*		if(common::GlobalData::verbose)
 			common::Streams::err << "Entry overload " + ss.str ( ) + " ambiguous. First selected." << std::endl;*/
 	} else {
-		std::stringstream ss;
-		ss << paramTypes;
-
-		throw std::invalid_argument ( "Entry overload " + ss.str ( ) + " not available." );
+		if ( templateParams.size ( ) == 0 )
+			throw std::invalid_argument ( "Entry overload " + name + " " + ext::to_string ( paramTypes ) + " not available" );
+		else
+			throw std::invalid_argument ( "Templated entry overload " + name + " < " + ext::to_string ( templateParams ) + " > " + ext::to_string ( paramTypes ) + " not available" );
 	}
 
 	return best->getAbstraction ( );
 }
 
-ext::set < std::string > AlgorithmRegistry::listGroup ( const std::string & group ) {
-	ext::set < std::string > res;
+ext::set < ext::pair < std::string, ext::vector < std::string > > > AlgorithmRegistry::listGroup ( const std::string & group ) {
+	ext::set < ext::pair < std::string, ext::vector < std::string > > > res;
 
-	for ( const std::pair < const std::string, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > & entry : getEntries ( ) )
-		if ( entry.first.find ( group ) == 0 ) //found at the begining
+	for ( const std::pair < const ext::pair < std::string, ext::vector < std::string > >, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > & entry : getEntries ( ) )
+		if ( entry.first.first.find ( group ) == 0 ) //found at the begining
 			res.insert ( entry.first );
 
 	return res;
 }
 
-ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > AlgorithmRegistry::listOverloads ( const std::string & algorithm ) {
-	auto group = getEntries ( ).find ( algorithm );
-	if ( group == getEntries ( ).end ( ) )
-		throw std::invalid_argument ( "Entry " + algorithm + " not available" );
+ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > AlgorithmRegistry::listOverloads ( const std::string & algorithm, const ext::vector < std::string > & templateParams ) {
+	auto group = getEntries ( ).find ( ext::make_pair ( algorithm, templateParams ) );
+	if ( group == getEntries ( ).end ( ) ) {
+		if ( templateParams.size ( ) == 0 )
+			throw std::invalid_argument ( "Entry " + algorithm + " not available" );
+		else
+			throw std::invalid_argument ( "Templated entry " + algorithm + " < " + ext::to_string ( templateParams ) + " > not available" );
+	}
 
 	ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > res;
 	for ( const ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > & overloads : group->second )
@@ -167,10 +174,10 @@ ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std:
 	return res;
 }
 
-ext::set < std::string > AlgorithmRegistry::list ( ) {
-	ext::set < std::string > res;
+ext::set < ext::pair < std::string, ext::vector < std::string > > > AlgorithmRegistry::list ( ) {
+	ext::set < ext::pair < std::string, ext::vector < std::string > > > res;
 
-	for ( const std::pair < const std::string, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > & entry : getEntries ( ) )
+	for ( const std::pair < const ext::pair < std::string, ext::vector < std::string > >, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > & entry : getEntries ( ) )
 		res.insert ( entry.first );
 
 	return res;
diff --git a/alib2abstraction/src/registry/AlgorithmRegistry.hpp b/alib2abstraction/src/registry/AlgorithmRegistry.hpp
index 7bbbefa3e994e718d762a93b954773fc1e1a3665..1c82d37003af50b1b54995e828163a69d0e55f7b 100644
--- a/alib2abstraction/src/registry/AlgorithmRegistry.hpp
+++ b/alib2abstraction/src/registry/AlgorithmRegistry.hpp
@@ -65,8 +65,8 @@ class AlgorithmRegistry {
 		virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
 	};
 
-	static ext::map < std::string, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > & getEntries ( ) {
-		static ext::map < std::string, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > algorithmGroups;
+	static ext::map < ext::pair < std::string, ext::vector < std::string > >, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > & getEntries ( ) {
+		static ext::map < ext::pair < std::string, ext::vector < std::string > >, ext::vector < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > >, ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, std::shared_ptr < Entry > > > > > algorithmGroups;
 		return algorithmGroups;
 	};
 
@@ -101,75 +101,83 @@ class AlgorithmRegistry {
 		return ext::make_pair ( ext::to_string < typename std::decay < ReturnType >::type > ( ), abstraction::ParamQualifiers::paramQualifiers < ReturnType > ( ) );
 	}
 
-	static bool isRegistered ( const std::string & algorithm, AlgorithmCategories::AlgorithmCategory category, const ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > & params );
+	static bool isRegistered ( const std::string & algorithm, const ext::vector < std::string > & templateParams, AlgorithmCategories::AlgorithmCategory category, const ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > & params );
 
-	static void registerInternal ( std::string algorithm, AlgorithmCategories::AlgorithmCategory category, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params, std::shared_ptr < Entry > value );
+	static void registerInternal ( std::string algorithm, ext::vector < std::string > templateParams, AlgorithmCategories::AlgorithmCategory category, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params, std::shared_ptr < Entry > value );
 
 public:
 	template < class Algo, class ObjectType, class ReturnType, class ... ParamTypes >
 	static void registerMethod ( ReturnType ( ObjectType:: * callback ) ( ParamTypes ... ), std::string methodName, std::array < std::string, sizeof ... ( ParamTypes ) > paramNames ) {
 		AlgorithmCategories::AlgorithmCategory category = AlgorithmCategories::AlgorithmCategory::DEFAULT;
 		std::string algorithm = ext::to_string < Algo > ( ) + "::" + methodName;
+		ext::vector < std::string > templateParams;
 
 		ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params = convertParamTypes < ParamTypes ... > ( paramNames );
 		params.insert ( params.begin ( ), convertParamType < ObjectType & > ( "object" ) );
 
 		ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result = convertReturnType < ReturnType > ( );
 
-		if ( isRegistered ( algorithm, category, params ) )
+		if ( isRegistered ( algorithm, templateParams, category, params ) )
 			throw std::invalid_argument ( "Callback for " + algorithm + " already registered." );
 
-		registerInternal ( std::move ( algorithm ), category, std::move ( result ), std::move ( params ), std::make_shared < MemberImpl < ObjectType &, ReturnType, ParamTypes ... > > ( callback ) );
+		registerInternal ( std::move ( algorithm ), std::move ( templateParams ), category, std::move ( result ), std::move ( params ), std::make_shared < MemberImpl < ObjectType &, ReturnType, ParamTypes ... > > ( callback ) );
 	}
 
 	template < class Algo, class ObjectType, class ReturnType, class ... ParamTypes >
 	static void registerMethod ( ReturnType ( ObjectType:: * callback ) ( ParamTypes ... ) const, std::string methodName, std::array < std::string, sizeof ... ( ParamTypes ) > paramNames ) {
 		AlgorithmCategories::AlgorithmCategory category = AlgorithmCategories::AlgorithmCategory::DEFAULT;
 		std::string algorithm = ext::to_string < Algo > ( ) + "::" + methodName;
+		ext::vector < std::string > templateParams;
 
 		ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params = convertParamTypes < ParamTypes ... > ( paramNames );
 		params.insert ( params.begin ( ), convertParamType < const ObjectType & > ( "object" ) );
 
 		ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result = convertReturnType < ReturnType > ( );
 
-		if ( isRegistered ( algorithm, category, params ) )
+		if ( isRegistered ( algorithm, templateParams, category, params ) )
 			throw std::invalid_argument ( "Callback for " + algorithm + " already registered." );
 
-		registerInternal ( std::move ( algorithm ), category, std::move ( result ), std::move ( params ), std::make_shared < MemberImpl < const ObjectType &, ReturnType, ParamTypes ... > > ( callback ) );
+		registerInternal ( std::move ( algorithm ), std::move ( templateParams ), category, std::move ( result ), std::move ( params ), std::make_shared < MemberImpl < const ObjectType &, ReturnType, ParamTypes ... > > ( callback ) );
 	}
 
 	template < class Algo, class ReturnType, class ... ParamTypes >
 	static void registerAlgorithm ( ReturnType ( * callback ) ( ParamTypes ... ), AlgorithmCategories::AlgorithmCategory category, std::array < std::string, sizeof ... ( ParamTypes ) > paramNames ) {
 		std::string algorithm = ext::to_string < Algo > ( );
+		ext::vector < std::string > templateParams;
+
 		ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params = convertParamTypes < ParamTypes ... > ( paramNames );
 		ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result = convertReturnType < ReturnType > ( );
 
-		if ( isRegistered ( algorithm, category, params ) )
+		if ( isRegistered ( algorithm, templateParams, category, params ) )
 			throw std::invalid_argument ( "Callback for " + algorithm + " already registered." );
 
-		registerInternal ( std::move ( algorithm ), category, std::move ( result ), std::move ( params ), std::make_shared < EntryImpl < ReturnType, ParamTypes ... > > ( callback ) );
+		registerInternal ( std::move ( algorithm ), std::move ( templateParams ), category, std::move ( result ), std::move ( params ), std::make_shared < EntryImpl < ReturnType, ParamTypes ... > > ( callback ) );
 	}
 
 	template < class Algo, class ... ParamTypes >
 	static void registerWrapper ( std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( ParamTypes ... ), std::array < std::string, sizeof ... ( ParamTypes ) > paramNames ) {
 		AlgorithmCategories::AlgorithmCategory category = AlgorithmCategories::AlgorithmCategory::DEFAULT;
+
 		std::string algorithm = ext::to_string < Algo > ( );
+		ext::vector < std::string > templateParams = ext::get_template_info ( algorithm );
+		algorithm = ext::erase_template_info ( algorithm );
+
 		ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > params = convertParamTypes < ParamTypes ... > ( paramNames );
 		ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > result = dynamicReturnType ( );
 
-		if ( isRegistered ( algorithm, category, params ) )
+		if ( isRegistered ( algorithm, templateParams, category, params ) )
 			return;
 
-		registerInternal ( std::move ( algorithm ), category, std::move ( result ), std::move ( params ), std::make_shared < WrapperImpl < ParamTypes ... > > ( callback ) );
+		registerInternal ( std::move ( algorithm ), std::move ( templateParams ), category, std::move ( result ), std::move ( params ), std::make_shared < WrapperImpl < ParamTypes ... > > ( callback ) );
 	}
 
-	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory category );
+	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory category );
 
-	static ext::set < std::string > listGroup ( const std::string & group );
+	static ext::set < ext::pair < std::string, ext::vector < std::string > > > listGroup ( const std::string & group );
 
-	static ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > listOverloads ( const std::string & algorithm );
+	static ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > listOverloads ( const std::string & algorithm, const ext::vector < std::string > & templateParams );
 
-	static ext::set < std::string > list ( );
+	static ext::set < ext::pair < std::string, ext::vector < std::string > > > list ( );
 };
 
 } /* namespace abstraction */
diff --git a/alib2abstraction/src/registry/Registry.cpp b/alib2abstraction/src/registry/Registry.cpp
index f938ec94f917a9a065fa5c76262cb9a3166388fe..4664955b31757224576c2068a47c188f6d436c46 100644
--- a/alib2abstraction/src/registry/Registry.cpp
+++ b/alib2abstraction/src/registry/Registry.cpp
@@ -16,11 +16,11 @@
 
 namespace abstraction {
 
-ext::set < std::string > Registry::listAlgorithmGroup ( const std::string & group ) {
+ext::set < ext::pair < std::string, ext::vector < std::string > > > Registry::listAlgorithmGroup ( const std::string & group ) {
 	return AlgorithmRegistry::listGroup ( group );
 }
 
-ext::set < std::string > Registry::listAlgorithms ( ) {
+ext::set < ext::pair < std::string, ext::vector < std::string > > > Registry::listAlgorithms ( ) {
 	return AlgorithmRegistry::list ( );
 }
 
@@ -36,16 +36,16 @@ ext::set < ext::pair < std::string, std::string > > Registry::listCasts ( ) {
 	return CastRegistry::list ( );
 }
 
-ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > Registry::listOverloads ( const std::string & algorithm ) {
-	return AlgorithmRegistry::listOverloads ( algorithm );
+ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > Registry::listOverloads ( const std::string & algorithm, const ext::vector < std::string > & templateParams ) {
+	return AlgorithmRegistry::listOverloads ( algorithm, templateParams );
 }
 
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getContainerAbstraction ( const std::string & container, const std::string & type ) {
 	return ContainerRegistry::getAbstraction ( container, type );
 }
 
-std::shared_ptr < abstraction::OperationAbstraction > Registry::getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory category ) {
-	return AlgorithmRegistry::getAbstraction ( name, paramTypes, category );
+std::shared_ptr < abstraction::OperationAbstraction > Registry::getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory category ) {
+	return AlgorithmRegistry::getAbstraction ( name, templateParams, paramTypes, category );
 }
 
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getCastAbstraction ( const std::string & target, const std::string & param ) {
diff --git a/alib2abstraction/src/registry/Registry.h b/alib2abstraction/src/registry/Registry.h
index b65f6a23afd22cd9c9b12be874aa93ca71c1ef54..7595c8bab814fed36f6f0ef89aa6a5428c1b1fea 100644
--- a/alib2abstraction/src/registry/Registry.h
+++ b/alib2abstraction/src/registry/Registry.h
@@ -19,17 +19,17 @@ namespace abstraction {
 
 class Registry {
 public:
-	static ext::set < std::string > listAlgorithmGroup ( const std::string & group );
-	static ext::set < std::string > listAlgorithms ( );
+	static ext::set < ext::pair < std::string, ext::vector < std::string > > > listAlgorithmGroup ( const std::string & group );
+	static ext::set < ext::pair < std::string, ext::vector < std::string > > > listAlgorithms ( );
 
 	static ext::set < std::string > listCastsFrom ( const std::string & type );
 	static ext::set < std::string > listCastsTo ( const std::string & type );
 	static ext::set < ext::pair < std::string, std::string > > listCasts ( );
 
-	static ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > listOverloads ( const std::string & algorithm );
+	static ext::set < ext::tuple < AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > listOverloads ( const std::string & algorithm, const ext::vector < std::string > & templateParams );
 
 	static std::shared_ptr < abstraction::OperationAbstraction > getContainerAbstraction ( const std::string & container, const std::string & type );
-	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory );
+	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::string > & paramTypes, AlgorithmCategories::AlgorithmCategory );
 	static std::shared_ptr < abstraction::OperationAbstraction > getCastAbstraction ( const std::string & target, const std::string & param );
 	static bool isCastNoOp ( const std::string & target, const std::string & param );
 	static std::shared_ptr < abstraction::OperationAbstraction > getImmediateAbstraction ( const std::string & result, std::string value );
diff --git a/alib2cli/src/ast/statements/SingleStatement.cpp b/alib2cli/src/ast/statements/SingleStatement.cpp
index 7c859347cc13e10243b41495af4680fc7fe58319..c9289f8c16b4e3819fc73b447bf1bedc40bed964 100644
--- a/alib2cli/src/ast/statements/SingleStatement.cpp
+++ b/alib2cli/src/ast/statements/SingleStatement.cpp
@@ -6,7 +6,7 @@
 
 namespace cli {
 
-SingleStatement::SingleStatement ( std::unique_ptr < Arg > name, ext::vector < std::unique_ptr < Param > > params, std::unique_ptr < CategoryOption > category ) : m_name ( std::move ( name ) ), m_params ( std::move ( params ) ), m_category ( std::move ( category ) ) {
+SingleStatement::SingleStatement ( std::unique_ptr < Arg > name, ext::vector < std::unique_ptr < cli::Arg > > templateParams, ext::vector < std::unique_ptr < Param > > params, std::unique_ptr < CategoryOption > category ) : m_name ( std::move ( name ) ), m_templateParams ( std::move ( templateParams ) ), m_params ( std::move ( params ) ), m_category ( std::move ( category ) ) {
 }
 
 std::shared_ptr < abstraction::OperationAbstraction > SingleStatement::translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const {
@@ -21,11 +21,16 @@ std::shared_ptr < abstraction::OperationAbstraction > SingleStatement::translate
 	}
 
 	std::string name = m_name->eval ( environment );
+
+	ext::vector < std::string > templateParams;
+	for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams )
+		templateParams.push_back ( templateParam->eval ( environment ) );
+
 	abstraction::AlgorithmCategories::AlgorithmCategory category = abstraction::AlgorithmCategories::AlgorithmCategory::NONE;
 	if ( m_category )
 		category = m_category->getCategory ( );
 
-	return abstraction::AlgorithmHelper::eval ( name, params, moves, category );
+	return abstraction::AlgorithmHelper::eval ( name, templateParams, params, moves, category );
 }
 
 } /* namespace cli */
diff --git a/alib2cli/src/ast/statements/SingleStatement.h b/alib2cli/src/ast/statements/SingleStatement.h
index 080274d98a1eaa62f0a31758c20cade5737d4924..21da6e6a5d75314585f9474dcfb78a06e5431baa 100644
--- a/alib2cli/src/ast/statements/SingleStatement.h
+++ b/alib2cli/src/ast/statements/SingleStatement.h
@@ -9,11 +9,12 @@ namespace cli {
 
 class SingleStatement final : public Statement {
 	std::unique_ptr < cli::Arg > m_name;
+	ext::vector < std::unique_ptr < cli::Arg > > m_templateParams;
 	ext::vector < std::unique_ptr < Param > > m_params;
 	std::unique_ptr < CategoryOption > m_category;
 
 public:
-	SingleStatement ( std::unique_ptr < cli::Arg > name, ext::vector < std::unique_ptr < Param > > params, std::unique_ptr < CategoryOption > options );
+	SingleStatement ( std::unique_ptr < cli::Arg > name, ext::vector < std::unique_ptr < cli::Arg > > templateParams, ext::vector < std::unique_ptr < Param > > params, std::unique_ptr < CategoryOption > options );
 
 	virtual std::shared_ptr < abstraction::OperationAbstraction > translateAndEval ( const std::shared_ptr < abstraction::OperationAbstraction > & prev, Environment & environment ) const override;
 };
diff --git a/alib2cli/src/command/AlgorithmsIntrospectionCommand.h b/alib2cli/src/command/AlgorithmsIntrospectionCommand.h
index 8dc73efd2ded41f3dbace80b5b75094113b18bd7..2f59919be172f6742e7977ac8a54e98a2a904305 100644
--- a/alib2cli/src/command/AlgorithmsIntrospectionCommand.h
+++ b/alib2cli/src/command/AlgorithmsIntrospectionCommand.h
@@ -13,9 +13,16 @@ public:
 	AlgorithmsIntrospectionCommand ( std::unique_ptr < cli::Arg > param ) : m_param ( std::move ( param ) ) {
 	}
 
-	void printAlgos ( const ext::set < std::string > & algos ) const {
-		for ( const std::string & algo : algos )
-			common::Streams::out << algo << std::endl;
+	void printAlgos ( const ext::set < ext::pair < std::string, ext::vector < std::string > > > & algos ) const {
+		for ( const ext::pair < std::string, ext::vector < std::string > > & algo : algos ) {
+			common::Streams::out << algo.first;
+			if ( algo.second.size ( ) != 0 ) {
+				common::Streams::out << " @";
+				for ( const std::string & templateParam : algo.second )
+					common::Streams::out << templateParam;
+			}
+			common::Streams::out << std::endl;
+		}
 	}
 
 	virtual Command::Result run ( Environment & environment ) const override {
diff --git a/alib2cli/src/command/HelpCommand.h b/alib2cli/src/command/HelpCommand.h
index cae2b64cbb55e5bc7f67fb4f9a7f236984924695..dedd7ed08382897a0b136bc11e0694d8ca1c26e8 100644
--- a/alib2cli/src/command/HelpCommand.h
+++ b/alib2cli/src/command/HelpCommand.h
@@ -30,6 +30,9 @@ public:
 			common::Streams::out << "value  - immediate string value" << std::endl;
 			common::Streams::out << "#value - string value from environmet variable" << std::endl;
 			common::Streams::out << "" << std::endl;
+			common::Streams::out << "template_param:" << std::endl;
+			common::Streams::out << "@ arg       - template param given by arg value" << std::endl;
+			common::Streams::out << "" << std::endl;
 			common::Streams::out << "param:" << std::endl;
 			common::Streams::out << "[^] -                   - a value from the previous result (PreviousResultParam)" << std::endl;
 			common::Streams::out << "[^] <( statement_list ) - a statement list serving as a param (StatementParam)" << std::endl;
@@ -43,7 +46,7 @@ public:
 			common::Streams::out << "<arg        - a value from a xml file, filename is given by arg value (FileParam)" << std::endl;
 			common::Streams::out << "" << std::endl;
 			common::Streams::out << "statement:" << std::endl;
-			common::Streams::out << "name ( param )* output_spec - a statement with params, name is an immediate value (SingleStatement)" << std::endl;
+			common::Streams::out << "name ( template_param )* ( param )* output_spec - a statement with params, name is an immediate value (SingleStatement)" << std::endl;
 			common::Streams::out << "( type ) [^] statement      - the result of a statement is casted, type is given by value (CastedStatement)" << std::endl;
 			common::Streams::out << "{ :type ( statement ) * }   - creates a set of type given by arg value with content values from individual statements" << std::endl;
 			common::Streams::out << "" << std::endl;
diff --git a/alib2cli/src/command/OverloadsIntrospectionCommand.h b/alib2cli/src/command/OverloadsIntrospectionCommand.h
index 060c74c088c6be4bfe9df298599dc0714be737a8..1ab01ede3495785399b418d46328f631b023ba52 100644
--- a/alib2cli/src/command/OverloadsIntrospectionCommand.h
+++ b/alib2cli/src/command/OverloadsIntrospectionCommand.h
@@ -8,15 +8,19 @@ namespace cli {
 
 class OverloadsIntrospectionCommand : public Command {
 	std::unique_ptr < cli::Arg > m_param;
+	ext::vector < std::unique_ptr < cli::Arg > > m_templateParams;
 
 public:
-	OverloadsIntrospectionCommand ( std::unique_ptr < cli::Arg > param ) : m_param ( std::move ( param ) ) {
+	OverloadsIntrospectionCommand ( std::unique_ptr < cli::Arg > param, ext::vector < std::unique_ptr < cli::Arg > > templateParams ) : m_param ( std::move ( param ) ), m_templateParams ( std::move ( templateParams ) ) {
 	}
 
 	virtual Command::Result run ( Environment & environment ) const override {
 		std::string param = m_param->eval ( environment );
+		ext::vector < std::string > templateParams;
+		for ( const std::unique_ptr < cli::Arg > & templateParam : m_templateParams )
+			templateParams.push_back ( templateParam->eval ( environment ) );
 
-		ext::set < ext::tuple < abstraction::AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > overloads = abstraction::Registry::listOverloads ( param );
+		ext::set < ext::tuple < abstraction::AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > > overloads = abstraction::Registry::listOverloads ( param, templateParams );
 		for ( const ext::tuple < abstraction::AlgorithmCategories::AlgorithmCategory, ext::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > >, ext::vector < ext::tuple < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier >, std::string > > > & overload : overloads ) {
 			common::Streams::out << std::get < 0 > ( overload ) << ": ";
 			{
diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp
index ad591d4d06a0337217ca111a4e1254f824d866cc..3a78632b4c8f43ae4f6826478bf5a62ca0972d68 100644
--- a/alib2cli/src/lexer/Lexer.cpp
+++ b/alib2cli/src/lexer/Lexer.cpp
@@ -55,6 +55,11 @@ q0:	if ( m_index >= m_line.size ( ) ) {
 		res.m_type = TokenType::RIGHT_BRACKET;
 		return res;
 	}
+	if ( m_line [ m_index ] == '@' ) {
+		m_index ++;
+		res.m_type = TokenType::AT_SIGN;
+		return res;
+	}
 	if ( m_line [ m_index ] == '$' ) {
 		m_index ++;
 		res.m_type = TokenType::DOLAR_SIGN;
diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h
index 8e56b887ac2d4ca531899a01728ddadbd9754113..654cafeeb487bb4202ca178e3eb4f29c3f03d14f 100644
--- a/alib2cli/src/lexer/Lexer.h
+++ b/alib2cli/src/lexer/Lexer.h
@@ -24,6 +24,7 @@ public:
 		LEFT_BRACKET,
 		RIGHT_BRACKET,
 		DOLAR_SIGN,
+		AT_SIGN,
 		AMPERSAND_SIGN,
 		PIPE_SIGN,
 		CARET_SIGN,
@@ -67,6 +68,8 @@ public:
 				return out << "left_bracket";
 			case TokenType::RIGHT_BRACKET :
 				return out << "right_bracket";
+			case TokenType::AT_SIGN :
+				return out << "at_sign";
 			case TokenType::DOLAR_SIGN :
 				return out << "dolar_sign";
 			case TokenType::AMPERSAND_SIGN :
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index 8707da1458b565c319ba3e97fe35251ec0bfc4bf..10cbcd486670d3543c758cdac964dee45ff163b8 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -105,6 +105,11 @@ std::unique_ptr < Param > Parser::in_redirect_param ( ) {
 	}
 }
 
+std::unique_ptr < Arg > Parser::template_param ( ) {
+	match ( cli::Lexer::TokenType::AT_SIGN );
+	return arg ( );
+}
+
 std::unique_ptr < Param > Parser::param ( ) {
 	if ( check ( cli::Lexer::TokenType::CARET_SIGN ) ) {
 		match ( cli::Lexer::TokenType::CARET_SIGN );
@@ -202,13 +207,18 @@ std::shared_ptr < Statement > Parser::single_statement ( ) {
 	// TODO builtin statement type to get string type
 	} else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) {
 		std::unique_ptr < Arg > name = std::make_unique < ImmediateArg > ( matchIdentifier ( ) );
+		ext::vector < std::unique_ptr < cli::Arg > > templateParams;
+		while ( check ( cli::Lexer::TokenType::AT_SIGN ) ) {
+			templateParams.emplace_back ( template_param ( ) );
+		}
+
 		std::unique_ptr < CategoryOption > category = category_option ( );
 		ext::vector < std::unique_ptr < Param > > params;
 		while ( ! check ( cli::Lexer::TokenType::OUT_REDIRECT ) && ! check ( cli::Lexer::TokenType::PIPE_SIGN ) && ! check ( cli::Lexer::TokenType::END ) && ! check ( cli::Lexer::TokenType::RIGHT_PAREN ) ) {
 			params.emplace_back ( param ( ) );
 		}
 
-		return std::make_shared < SingleStatement > ( std::move ( name ), std::move ( params ), std::move ( category ) );
+		return std::make_shared < SingleStatement > ( std::move ( name ), std::move ( templateParams ), std::move ( params ), std::move ( category ) );
 	} else if ( check ( cli::Lexer::TokenType::LEFT_BRACE ) ) {
 		match ( cli::Lexer::TokenType::LEFT_BRACE );
 		std::unique_ptr < TypeOption > type = type_option ( );
@@ -297,8 +307,14 @@ std::unique_ptr < Command > Parser::introspect_command ( ) {
 	} else if ( check_nonreserved_kw ( "overloads" ) ) {
 		match_nonreserved_kw ( "overloads" );
 		std::unique_ptr < cli::Arg > param = arg ( );
+
+		ext::vector < std::unique_ptr < cli::Arg > > templateParams;
+		while ( check ( cli::Lexer::TokenType::AT_SIGN ) ) {
+			templateParams.emplace_back ( template_param ( ) );
+		}
+
 		match ( cli::Lexer::TokenType::END );
-		return std::make_unique < OverloadsIntrospectionCommand > ( std::move ( param ) );
+		return std::make_unique < OverloadsIntrospectionCommand > ( std::move ( param ), std::move ( templateParams ) );
 	} else if ( check_nonreserved_kw ( "datatypes" ) ) {
 		match_nonreserved_kw ( "datatypes" );
 		std::unique_ptr < cli::Arg > param = optional_arg ( );
diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h
index 483ea520a035a3544286db8204345ee6e25fc2ff..054e31c1ab61ba5574ea78e730ed7015d05c8b92 100644
--- a/alib2cli/src/parser/Parser.h
+++ b/alib2cli/src/parser/Parser.h
@@ -95,6 +95,8 @@ public:
 	std::unique_ptr < Param > in_redirect_param ( );
 
 	std::unique_ptr < Param > param ( );
+	
+	std::unique_ptr < Arg > template_param ( );
 
 	std::unique_ptr < Param > move_param ( );
 
diff --git a/alib2raw/src/abstraction/RawReaderAbstraction.hpp b/alib2raw/src/abstraction/RawReaderAbstraction.hpp
index d7c726a27d027e38acceb6739bc4714c599edda1..f1bdf0d063cb742659f34b9b18d5c405d6a6fa71 100644
--- a/alib2raw/src/abstraction/RawReaderAbstraction.hpp
+++ b/alib2raw/src/abstraction/RawReaderAbstraction.hpp
@@ -8,19 +8,19 @@
 #ifndef _RAW_READER_ABSTRACTION_HPP_
 #define _RAW_READER_ABSTRACTION_HPP_
 
-#include <abstraction/BinaryOperationAbstraction.hpp>
+#include <abstraction/UnaryOperationAbstraction.hpp>
 #include <factory/RawDataFactory.hpp>
 
 namespace abstraction {
 
 template < class ReturnType >
-class RawReaderAbstraction : public BinaryOperationAbstraction < ReturnType, const std::string &, std::string && > {
+class RawReaderAbstraction : public UnaryOperationAbstraction < ReturnType, std::string && > {
 public:
 	virtual bool run ( ) override {
 		if ( this->isReady ( ) )
 			return true;
 
-		ReturnType res = alib::RawDataFactory::fromString ( std::get < 1 > ( this->m_params )->getRValueReference ( ) );
+		ReturnType res = alib::RawDataFactory::fromString ( std::get < 0 > ( this->m_params )->getRValueReference ( ) );
 		this->m_data = std::move ( res );
 		return true;
 	}
diff --git a/alib2raw/src/registration/RawRegistration.hpp b/alib2raw/src/registration/RawRegistration.hpp
index 35f056fd761739d229387036fafffcb953e9e843..8240e2589d39132e1d5739ce8efcf8eb33f48fe5 100644
--- a/alib2raw/src/registration/RawRegistration.hpp
+++ b/alib2raw/src/registration/RawRegistration.hpp
@@ -10,10 +10,11 @@
 
 namespace raw {
 
+template < class Type >
 class Parse {
 public:
-	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromString ( const std::string & type, const std::string & ) {
-		return abstraction::RawReaderRegistry::getAbstraction ( type );
+	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromString ( const std::string & ) {
+		return abstraction::RawReaderRegistry::getAbstraction ( ext::to_string < Type > ( ) );
 	}
 
 };
@@ -36,7 +37,7 @@ class RawReaderRegister {
 public:
 	RawReaderRegister ( ) {
 		abstraction::RawReaderRegistry::registerRawReader < Type > ( );
-		abstraction::AlgorithmRegistry::registerWrapper < raw::Parse, const std::string &, const std::string & > ( raw::Parse::abstractionFromString, std::array < std::string, 2 > { } );
+		abstraction::AlgorithmRegistry::registerWrapper < raw::Parse < Type >, const std::string & > ( raw::Parse < Type >::abstractionFromString, std::array < std::string, 1 > { } );
 	}
 };
 
diff --git a/alib2str/src/abstraction/StringReaderAbstraction.hpp b/alib2str/src/abstraction/StringReaderAbstraction.hpp
index fe5f78000984c5101065a80aa91b154d425556bb..495b68e0f07dc7f14661946864c059933f7f6a1e 100644
--- a/alib2str/src/abstraction/StringReaderAbstraction.hpp
+++ b/alib2str/src/abstraction/StringReaderAbstraction.hpp
@@ -8,19 +8,19 @@
 #ifndef _STRING_READER_ABSTRACTION_HPP_
 #define _STRING_READER_ABSTRACTION_HPP_
 
-#include <abstraction/BinaryOperationAbstraction.hpp>
+#include <abstraction/UnaryOperationAbstraction.hpp>
 #include <factory/StringDataFactory.hpp>
 
 namespace abstraction {
 
 template < class ReturnType >
-class StringReaderAbstraction : public BinaryOperationAbstraction < ReturnType, const std::string &, std::string && > {
+class StringReaderAbstraction : public UnaryOperationAbstraction < ReturnType, std::string && > {
 public:
 	virtual bool run ( ) override {
 		if ( this->isReady ( ) )
 			return true;
 
-		ReturnType res = alib::StringDataFactory::fromString ( std::get < 1 > ( this->m_params )->getRValueReference ( ) );
+		ReturnType res = alib::StringDataFactory::fromString ( std::get < 0 > ( this->m_params )->getRValueReference ( ) );
 		this->m_data = std::move ( res );
 		return true;
 	}
diff --git a/alib2str/src/registration/StringRegistration.hpp b/alib2str/src/registration/StringRegistration.hpp
index 9b5d0b637f3abc4b2df81d42517f212e75685a67..8ae0e1a10eeaebe0b44deacaef843b45bfb025ec 100644
--- a/alib2str/src/registration/StringRegistration.hpp
+++ b/alib2str/src/registration/StringRegistration.hpp
@@ -10,10 +10,11 @@
 
 namespace string {
 
+template < class Group >
 class Parse {
 public:
-	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromString ( const std::string & group, std::string && data ) {
-		return abstraction::StringReaderRegistry::getAbstraction ( group, data );
+	static std::shared_ptr < abstraction::OperationAbstraction > abstractionFromString ( std::string && data ) {
+		return abstraction::StringReaderRegistry::getAbstraction ( ext::to_string < Group > ( ), data );
 	}
 
 };
@@ -38,7 +39,7 @@ public:
 		alib::stringApi < Group >::template registerStringReader < Type > ( );
 
 		abstraction::StringReaderRegistry::registerStringReader < Group, Type > ( );
-		abstraction::AlgorithmRegistry::registerWrapper < string::Parse, const std::string &, std::string && > ( string::Parse::abstractionFromString, std::array < std::string, 2 > { } );
+		abstraction::AlgorithmRegistry::registerWrapper < string::Parse < Group >, std::string && > ( string::Parse < Group >::abstractionFromString, std::array < std::string, 1 > { } );
 	}
 };
 
diff --git a/araw2/src/araw.cpp b/araw2/src/araw.cpp
index 6f088cde020beee8fd02a5de6802cce329772813..029074ae09ddac2310a88b94006e8b66e45af90d 100644
--- a/araw2/src/araw.cpp
+++ b/araw2/src/araw.cpp
@@ -76,11 +76,11 @@ int main(int argc, char** argv) {
 		measurements::start ( "Algorithm", measurements::Type::MAIN );
 
 		if(tree_from_raw.getValue()) {
-			parser = cli::Parser ( cli::Lexer ( "execute raw::Parse tree::UnrankedTree $input > $output" ) );
+			parser = cli::Parser ( cli::Lexer ( "execute raw::Parse @ tree::UnrankedTree $input > $output" ) );
 		} else if(tree_to_raw.getValue()) {
 			parser = cli::Parser ( cli::Lexer ( "execute raw::Compose $input > $output" ) );
 		} else if(string_from_raw.getValue()) {
-			parser = cli::Parser ( cli::Lexer ( "execute raw::Parse string::LinearString $input > $output" ) );
+			parser = cli::Parser ( cli::Lexer ( "execute raw::Parse @ string::LinearString $input > $output" ) );
 		} else if(string_to_raw.getValue()) {
 			parser = cli::Parser ( cli::Lexer ( "execute raw::Compose $input > $output" ) );
 		} else {
diff --git a/docs/userGuide/userGuide.tex b/docs/userGuide/userGuide.tex
index 7d728266ccddb021247960c48d94c8fdcd3cfd4a..3493d48b5b98a5273ae9ab499bf893ad2ad3d8e8 100644
--- a/docs/userGuide/userGuide.tex
+++ b/docs/userGuide/userGuide.tex
@@ -210,11 +210,11 @@ introspect casts :to int
 
 \section{Interactive}
 
-execute cli::builtin::ReadFile ../examples2/automaton/DFA.txt | string::Parse automaton::Automaton \^{} -
+execute cli::builtin::ReadFile ../examples2/automaton/DFA.txt | string::Parse @ automaton::Automaton \^{} -
 
 \section{Command line execution}
 
-./aql2 -p input=../examples2/automaton/DFA.txt -q 'execute cli::builtin::ReadFile \#input > \$in' -q 'execute string::Parse automaton::Automaton \^{} \$in'
+./aql2 -p input=../examples2/automaton/DFA.txt -q 'execute cli::builtin::ReadFile \#input > \$in' -q 'execute string::Parse @ automaton::Automaton \^{} \$in'
 
 \noindent
 ./aql2 -q 'execute automaton::simplify::efficient::EpsilonRemoverIncoming <\#stdin | automaton::determinize::Determinize - | automaton::simplify::Trim - | automaton::simplify::Minimize - | automaton::simplify::Normalize - >\#stdout'