From 9aa458a4bd14b6cdf45be58f0628ec4ffe67b26c Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 19 May 2016 13:48:15 +0200
Subject: [PATCH] support more components

---
 alib2common/src/core/components.hpp            | 18 ++++++++++++------
 alib2std/src/extensions/type_traits.hpp        | 12 ++++++++++++
 .../test-src/extensions/TypeTraitsTest.cpp     |  5 +++++
 alib2std/test-src/extensions/TypeTraitsTest.h  |  2 ++
 4 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/alib2common/src/core/components.hpp b/alib2common/src/core/components.hpp
index da11582560..89c49c6e09 100644
--- a/alib2common/src/core/components.hpp
+++ b/alib2common/src/core/components.hpp
@@ -305,7 +305,7 @@ struct ComponentAux < Derived, SymbolType, tuple < SetTypes ... > > : public Com
 	 * @param SetType alphabet type used to distinguish different sub alphabets
 	 * @return sub-component
 	 */
-	template < class SetType >
+	template < class SetType, typename std::enable_if < std::is_in < SetType, SetTypes ... >::value >::type * = nullptr >
 	const Component < Derived, SymbolType, SetType > & accessComponent ( ) const {
 		return static_cast < const Component < Derived, SymbolType, SetType > & > ( * this );
 	}
@@ -315,7 +315,7 @@ struct ComponentAux < Derived, SymbolType, tuple < SetTypes ... > > : public Com
 	 * @param SetType alphabet type used to distinguish different sub alphabets
 	 * @return sub-component
 	 */
-	template < class SetType >
+	template < class SetType, typename std::enable_if < std::is_in < SetType, SetTypes ... >::value >::type * = nullptr >
 	Component < Derived, SymbolType, SetType > & accessComponent ( ) {
 		return static_cast < Component < Derived, SymbolType, SetType > & > ( * this );
 	}
@@ -355,7 +355,7 @@ struct ElementAux < Derived, SymbolType, tuple < ElementTypes ... > > : public E
 	 * @param ElementType alphabet type used to distinguish different sub alphabets
 	 * @return sub-component
 	 */
-	template < class ElementType >
+	template < class ElementType, typename std::enable_if < std::is_in < ElementType, ElementTypes ... >::value >::type * = nullptr >
 	const Element < Derived, SymbolType, ElementType > & accessElement ( ) const {
 		return static_cast < const Element < Derived, SymbolType, ElementType > & > ( * this );
 	}
@@ -365,7 +365,7 @@ struct ElementAux < Derived, SymbolType, tuple < ElementTypes ... > > : public E
 	 * @param ElementType alphabet type used to distinguish different sub alphabets
 	 * @return sub-component
 	 */
-	template < class ElementType >
+	template < class ElementType, typename std::enable_if < std::is_in < ElementType, ElementTypes ... >::value >::type * = nullptr >
 	Element < Derived, SymbolType, ElementType > & accessElement ( ) {
 		return static_cast < Element < Derived, SymbolType, ElementType > & > ( * this );
 	}
@@ -409,12 +409,18 @@ public:
 	/**
 	 * Construct an alphabet pack from two alphabets.
 	 */
-	template < class RealSetTypes, class RealElementTypes >
-	Components ( RealSetTypes params1, RealElementTypes params2 ) : ComponentAux < Derived, SymbolType, SetTypesPack > ( std::move ( params1 ), std::make_index_sequence < std::tuple_size < SetTypesPack >::value > { } ), ElementAux < Derived, SymbolType, ElementTypesPack > ( std::move ( params2 ), std::make_index_sequence < std::tuple_size < ElementTypesPack >::value > { } ) {
+	template < class RealSetTypes, class RealElementTypes, class ... NextRealTypes >
+	Components ( RealSetTypes params1, RealElementTypes params2, NextRealTypes ... nextParams ) : ComponentAux < Derived, SymbolType, SetTypesPack > ( std::move ( params1 ), std::make_index_sequence < std::tuple_size < SetTypesPack >::value > { } ), ElementAux < Derived, SymbolType, ElementTypesPack > ( std::move ( params2 ), std::make_index_sequence < std::tuple_size < ElementTypesPack >::value > { } ), Components < Derived, NextGroup ... > ( std::move ( nextParams ) ... ) {
 		ComponentAux < Derived, SymbolType, SetTypesPack >::checkState ( );
 
 		ElementAux < Derived, SymbolType, ElementTypesPack >::checkState ( );
 	}
+
+	using ComponentAux < Derived, SymbolType, SetTypesPack >::accessComponent;
+	using ElementAux < Derived, SymbolType, ElementTypesPack >::accessElement;
+
+	using Components < Derived, NextGroup ... >::accessComponent;
+	using Components < Derived, NextGroup ... >::accessElement;
 };
 
 } /* namespace std */
diff --git a/alib2std/src/extensions/type_traits.hpp b/alib2std/src/extensions/type_traits.hpp
index 09755ae36c..8b3924ada4 100644
--- a/alib2std/src/extensions/type_traits.hpp
+++ b/alib2std/src/extensions/type_traits.hpp
@@ -45,6 +45,18 @@ namespace std {
 		typedef typename get_type_pack_element < N - 1, Ts ... >::type type;
 	};
 
+	template < typename T, typename ... Ts >
+	struct is_in;
+
+	template < typename T >
+	struct is_in < T > : std::false_type { };
+
+	template < typename T, typename U, typename ... Ts >
+	struct is_in < T, U, Ts ... > : is_in < T, Ts ... > { };
+
+	template < typename T, typename ... Ts >
+	struct is_in < T, T, Ts ... > : std::true_type { };
+
 } /* namespace std */
 
 #endif // TYPE_TRAITS_HPP_
diff --git a/alib2std/test-src/extensions/TypeTraitsTest.cpp b/alib2std/test-src/extensions/TypeTraitsTest.cpp
index 1fb9db2a2e..5790deafa8 100644
--- a/alib2std/test-src/extensions/TypeTraitsTest.cpp
+++ b/alib2std/test-src/extensions/TypeTraitsTest.cpp
@@ -20,3 +20,8 @@ void TypeTraitsTest::testIsBaseOf() {
 void TypeTraitsTest::testAccessPackElement() {
 	CPPUNIT_ASSERT( ( std::is_same< std::get_type_pack_element < 0, int, double >::type, int >::value ) == true );
 }
+
+void TypeTraitsTest::testTypeInPack() {
+	CPPUNIT_ASSERT( ( std::is_in< int, double, std::set<int>, float, char, int, std::string >::value ) == true );
+	CPPUNIT_ASSERT( ( std::is_in< long, double, std::set<int>, float, char, int, std::string >::value ) == false );
+}
diff --git a/alib2std/test-src/extensions/TypeTraitsTest.h b/alib2std/test-src/extensions/TypeTraitsTest.h
index aaa13c3681..43f01fc916 100644
--- a/alib2std/test-src/extensions/TypeTraitsTest.h
+++ b/alib2std/test-src/extensions/TypeTraitsTest.h
@@ -8,6 +8,7 @@ class TypeTraitsTest : public CppUnit::TestFixture
   CPPUNIT_TEST_SUITE( TypeTraitsTest );
   CPPUNIT_TEST( testIsBaseOf );
   CPPUNIT_TEST( testAccessPackElement );
+  CPPUNIT_TEST( testTypeInPack );
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -65,6 +66,7 @@ public:
 
   void testIsBaseOf();
   void testAccessPackElement();
+  void testTypeInPack();
 };
 
 #endif  // TYPE_TRAITS_TEST_H_
-- 
GitLab