From c5828e622760e4a2569a762983eb868b97f24acf Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 24 Jan 2019 14:12:59 +0100
Subject: [PATCH] fix binding scheme of qualified values

---
 .../abstraction/ValueOperationAbstraction.hpp | 128 +++++++++++++++++-
 .../src/abstraction/ValueProvider.hpp         |  23 +++-
 2 files changed, 143 insertions(+), 8 deletions(-)

diff --git a/alib2abstraction/src/abstraction/ValueOperationAbstraction.hpp b/alib2abstraction/src/abstraction/ValueOperationAbstraction.hpp
index 8a022b6847..d2787e679c 100644
--- a/alib2abstraction/src/abstraction/ValueOperationAbstraction.hpp
+++ b/alib2abstraction/src/abstraction/ValueOperationAbstraction.hpp
@@ -25,6 +25,70 @@ class UnspecifiedType {
 template < class ReturnType >
 class ValueOperationAbstraction : public OperationAbstraction, public ValueProvider < ReturnType >, public ValueProvider < ReturnType & >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
 protected:
+	virtual bool isConst ( ) const override {
+		return false;
+	}
+
+	virtual bool isRvalueRef ( ) const override {
+		return false;
+	}
+
+	virtual bool isLvalueRef ( ) const override {
+		return false;
+	}
+
+	virtual ReturnType & getData ( ) const override {
+		return m_data.value ( );
+	}
+
+	virtual const ReturnType & getConstData ( ) const override {
+		return m_data.value ( );
+	}
+
+	mutable std::optional < ReturnType > m_data;
+
+public:
+	template < typename ... ParamTypes, typename Callable >
+	inline void run_helper ( Callable callback, const ext::array < std::pair < std::shared_ptr < OperationAbstraction >, bool >, sizeof ... ( ParamTypes ) > & inputs ) {
+		if ( ! cached ( ) )
+			m_data = abstraction::apply < ParamTypes ... > ( callback, inputs );
+	}
+
+	virtual ext::type_index getReturnTypeIndex ( ) const override {
+		return ext::type_index ( typeid ( ReturnType ) );
+	}
+
+	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
+		if ( cached ( ) )
+			return ext::type_index ( typeid ( getData ( ) ) );
+		else
+			throw std::domain_error ( "Runtime type unknown before evaluation." );
+	}
+
+	virtual bool cached ( ) const override {
+		return ( bool ) m_data;
+	}
+
+	virtual void reset ( ) override {
+		m_data.reset ( );
+	}
+};
+
+template < class ReturnType >
+class ValueOperationAbstraction < const ReturnType > : public OperationAbstraction, public ValueProvider < ReturnType >, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
+protected:
+	virtual bool isConst ( ) const override {
+		return true;
+	}
+
+	virtual bool isRvalueRef ( ) const override {
+		return false;
+	}
+
+	virtual bool isLvalueRef ( ) const override {
+		return false;
+	}
+
 	virtual ReturnType & getData ( ) const override {
 		return m_data.value ( );
 	}
@@ -63,8 +127,20 @@ public:
 };
 
 template < class ReturnType >
-class ValueOperationAbstraction < ReturnType & > : public OperationAbstraction, public ValueProvider < ReturnType & >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
+class ValueOperationAbstraction < ReturnType & > : public OperationAbstraction, public ValueProvider < ReturnType >, public ValueProvider < ReturnType & >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
 protected:
+	virtual bool isConst ( ) const override {
+		return false;
+	}
+
+	virtual bool isRvalueRef ( ) const override {
+		return true;
+	}
+
+	virtual bool isLvalueRef ( ) const override {
+		return false;
+	}
+
 	virtual ReturnType & getData ( ) const override {
 		return m_data->get ( );
 	}
@@ -103,8 +179,24 @@ public:
 };
 
 template < class ReturnType >
-class ValueOperationAbstraction < const ReturnType & > : public OperationAbstraction, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
+class ValueOperationAbstraction < const ReturnType & > : public OperationAbstraction, public ValueProvider < ReturnType >, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
 protected:
+	virtual bool isConst ( ) const override {
+		return true;
+	}
+
+	virtual bool isRvalueRef ( ) const override {
+		return true;
+	}
+
+	virtual bool isLvalueRef ( ) const override {
+		return false;
+	}
+
+	virtual ReturnType & getData ( ) const override {
+		return const_cast < ReturnType & > ( m_data->get ( ) );
+	}
+
 	virtual const ReturnType & getConstData ( ) const override {
 		return m_data->get ( );
 	}
@@ -139,8 +231,20 @@ public:
 };
 
 template < class ReturnType >
-class ValueOperationAbstraction < ReturnType && > : public OperationAbstraction, public ValueProvider < ReturnType & >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
+class ValueOperationAbstraction < ReturnType && > : public OperationAbstraction, public ValueProvider < ReturnType >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
 protected:
+	virtual bool isConst ( ) const override {
+		return false;
+	}
+
+	virtual bool isRvalueRef ( ) const override {
+		return false;
+	}
+
+	virtual bool isLvalueRef ( ) const override {
+		return true;
+	}
+
 	virtual ReturnType & getData ( ) const override {
 		return m_data->get ( );
 	}
@@ -181,8 +285,24 @@ public:
 };
 
 template < class ReturnType >
-class ValueOperationAbstraction < const ReturnType && > : public OperationAbstraction, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
+class ValueOperationAbstraction < const ReturnType && > : public OperationAbstraction, public ValueProvider < ReturnType >, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
 protected:
+	virtual bool isConst ( ) const override {
+		return true;
+	}
+
+	virtual bool isRvalueRef ( ) const override {
+		return false;
+	}
+
+	virtual bool isLvalueRef ( ) const override {
+		return true;
+	}
+
+	virtual ReturnType & getData ( ) const override {
+		return const_cast < ReturnType & > ( m_data->get ( ) );
+	}
+
 	virtual const ReturnType & getConstData ( ) const override {
 		return m_data->get ( );
 	}
diff --git a/alib2abstraction/src/abstraction/ValueProvider.hpp b/alib2abstraction/src/abstraction/ValueProvider.hpp
index 5966731609..56f77de7ee 100644
--- a/alib2abstraction/src/abstraction/ValueProvider.hpp
+++ b/alib2abstraction/src/abstraction/ValueProvider.hpp
@@ -17,12 +17,15 @@ namespace abstraction {
 template < class Type >
 class ValueProvider {
 protected:
+	virtual bool isConst ( ) const = 0;
+	virtual bool isLvalueRef ( ) const = 0;
+	virtual bool isRvalueRef ( ) const = 0;
 	virtual Type & getData ( ) const = 0;
 
 public:
 	template < class T = Type >
 	typename std::enable_if < std::is_copy_constructible < T >::value && std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const {
-		if ( move )
+		if ( ! isConst ( ) && move )
 			return std::move ( getData ( ) );
 		else
 			return getData ( );
@@ -30,7 +33,7 @@ public:
 
 	template < class T = Type >
 	typename std::enable_if < std::is_copy_constructible < T >::value && ! std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const {
-		if ( move )
+		if ( ! isConst ( ) && move )
 			throw std::domain_error ( "Value not move constructible" );
 		else
 			return getData ( );
@@ -38,7 +41,7 @@ public:
 
 	template < class T = Type >
 	typename std::enable_if < ! std::is_copy_constructible < T >::value && std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const {
-		if ( move )
+		if ( ! isConst ( ) && move )
 			return std::move ( getData ( ) );
 		else
 			throw std::domain_error ( "Value not copy constructible" );
@@ -46,7 +49,7 @@ public:
 
 	template < class T = Type >
 	typename std::enable_if < ! std::is_copy_constructible < T >::value && ! std::is_move_constructible < T >::value, T >::type getValue ( bool move ) const {
-		if ( move )
+		if ( ! isConst ( ) && move )
 			throw std::domain_error ( "Value not move constructible" );
 		else
 			throw std::domain_error ( "Value not copy constructible" );
@@ -58,6 +61,9 @@ public:
 template < class Type >
 class ValueProvider < Type & > {
 protected:
+	virtual bool isConst ( ) const = 0;
+	virtual bool isLvalueRef ( ) const = 0;
+	virtual bool isRvalueRef ( ) const = 0;
 	virtual Type & getData ( ) const = 0;
 
 public:
@@ -75,6 +81,9 @@ public:
 template < class Type >
 class ValueProvider < const Type & > {
 protected:
+	virtual bool isConst ( ) const = 0;
+	virtual bool isLvalueRef ( ) const = 0;
+	virtual bool isRvalueRef ( ) const = 0;
 	virtual const Type & getConstData ( ) const = 0;
 
 public:
@@ -92,6 +101,9 @@ public:
 template < class Type >
 class ValueProvider < Type && > {
 protected:
+	virtual bool isConst ( ) const = 0;
+	virtual bool isLvalueRef ( ) const = 0;
+	virtual bool isRvalueRef ( ) const = 0;
 	virtual Type & getData ( ) const = 0;
 
 public:
@@ -112,6 +124,9 @@ public:
 template < class Type >
 class ValueProvider < const Type && > {
 protected:
+	virtual bool isConst ( ) const = 0;
+	virtual bool isLvalueRef ( ) const = 0;
+	virtual bool isRvalueRef ( ) const = 0;
 	virtual const Type & getConstData ( ) const = 0;
 
 public:
-- 
GitLab