From a867771ab2323760dfbf01ccc39962bb83c9ae85 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 11 Aug 2017 16:34:25 +0200
Subject: [PATCH] fix detection of invalid template param on variant on get,
 set, is methods

---
 alib2std/src/extensions/variant.hpp           | 24 +++++++++----------
 .../test-src/extensions/TypeTraitsTest.cpp    |  2 ++
 alib2std/test-src/extensions/VariantTest.cpp  |  3 +++
 3 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/alib2std/src/extensions/variant.hpp b/alib2std/src/extensions/variant.hpp
index 5ebdcbb603..2a8fc2c581 100644
--- a/alib2std/src/extensions/variant.hpp
+++ b/alib2std/src/extensions/variant.hpp
@@ -219,7 +219,7 @@ class variant : public variant_base<static_max<SizeOf<Ts>::size...>, static_max<
 public:
 	using variant_base<static_max<SizeOf<Ts>::size...>, static_max<AlignOf<Ts>::align...>, Ts...>::variant_base;
 
-	template < typename = std::enable_if < ext::is_in<void, Ts...>::value > >
+	template < typename T = void, typename std::enable_if < ext::is_in<T, Ts...>::value >::type* = nullptr >
 	variant ( ) : variant_base<static_max<SizeOf<Ts>::size...>, static_max<AlignOf<Ts>::align...>, Ts...> ( ) {
 	}
 
@@ -279,33 +279,33 @@ public:
 		return helper_t::compareHelper(this->type_id, &this->data, other.type_id, &other.data);
 	}
 
-	template<typename T, typename = std::enable_if < ext::is_in<T, Ts...>::value > >
+	template<typename T, typename std::enable_if < ext::is_in<T, Ts...>::value >::type* = nullptr >
 	bool is() const {
 		return (this->type_id == typeid(T).hash_code());
 	}
 
-	template<typename = std::enable_if < ext::is_in<void, Ts...>::value > >
-	void set ( ) {
+	template < typename T = void >
+	typename std::enable_if < ext::is_in < T, Ts ... >::value, void >::type set ( ) {
 		helper_t::destroy(this->type_id, &this->data);
 		this->type_id = typeid(void).hash_code();
 	}
 
-	template<typename T, typename = std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value > >
-	void set(T&& value) {
+	template < typename T >
+	void set ( typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type && value ) {
 		helper_t::destroy(this->type_id, &this->data);
 		new (&this->data) T(value);
 		this->type_id = typeid(T).hash_code();
 	}
 
-	template<typename T, typename = std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value > >
-	void set(const T& value) {
+	template < typename T >
+	void set ( const typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type & value ) {
 		helper_t::destroy(this->type_id, &this->data);
 		new (&this->data) T(std::move(value));
 		this->type_id = typeid(T).hash_code();
 	}
 
-	template<typename T, typename = std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value > >
-	T& get() {
+	template < typename T >
+	typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type & get() {
 		// It is a dynamic_cast-like behaviour
 		if (this->type_id == typeid(T).hash_code())
 			return *reinterpret_cast<T*>(&this->data);
@@ -313,8 +313,8 @@ public:
 			throw std::bad_cast();
 	}
 
-	template<typename T, typename = std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value > >
-	const T& get() const {
+	template<typename T >
+	const typename std::enable_if < ext::is_in<T, Ts...>::value && ! std::is_same < void, T >::value, T >::type& get() const {
 		// It is a dynamic_cast-like behaviour
 		if (this->type_id == typeid(T).hash_code())
 			return *reinterpret_cast<const T*>(&this->data);
diff --git a/alib2std/test-src/extensions/TypeTraitsTest.cpp b/alib2std/test-src/extensions/TypeTraitsTest.cpp
index 411607ca19..378172ede6 100644
--- a/alib2std/test-src/extensions/TypeTraitsTest.cpp
+++ b/alib2std/test-src/extensions/TypeTraitsTest.cpp
@@ -17,4 +17,6 @@ void TypeTraitsTest::testAccessPackElement() {
 void TypeTraitsTest::testTypeInPack() {
 	CPPUNIT_ASSERT( ( ext::is_in< int, double, ext::set<int>, float, char, int, std::string >::value ) == true );
 	CPPUNIT_ASSERT( ( ext::is_in< long, double, ext::set<int>, float, char, int, std::string >::value ) == false );
+
+	CPPUNIT_ASSERT( ( ext::is_in< std::pair < int, int >, void, ext::pair < int, int > >::value ) == false );
 }
diff --git a/alib2std/test-src/extensions/VariantTest.cpp b/alib2std/test-src/extensions/VariantTest.cpp
index c051a5976c..c31c2701f1 100644
--- a/alib2std/test-src/extensions/VariantTest.cpp
+++ b/alib2std/test-src/extensions/VariantTest.cpp
@@ -114,6 +114,9 @@ void VariantTest::testVariantSet2() {
 	std::set_union(s.begin(), s.end(), t.begin(), t.end(), std::inserter(u, u.begin()));
 
 	CPPUNIT_ASSERT( s.size() == u.size());
+
+/*	ext::variant < void, ext::pair < int, int > > var;
+	var.get < int > ( );*///should not compile -- correct behavior
 }
 
 void VariantTest::testVariantVoid() {
-- 
GitLab