Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ValueOperationAbstraction.hpp 13.25 KiB
/*
 * ValueOperationAbstraction.hpp
 *
 *  Created on: 11. 7. 2017
 *	  Author: Jan Travnicek
 */

#ifndef _VALUE_OPERATION_ABSTRACTION_HPP_
#define _VALUE_OPERATION_ABSTRACTION_HPP_

#include <abstraction/OperationAbstraction.hpp>
#include <tuple>
#include <memory>
#include <typeindex>
#include <variant>
#include <abstraction/ValueProvider.hpp>

namespace abstraction {

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 ReturnType & getData ( ) const override {
		return m_data.template get < ReturnType > ( );
	}

	virtual const ReturnType & getConstData ( ) const override {
		return m_data.template get < ReturnType > ( );
	}

	mutable ext::variant < void, ReturnType > m_data;

public:
	template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes >
	inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) )
			m_data = callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... );
	}

	template < typename Callable, typename ... Ts, size_t ... Indexes >
	inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) )
			m_data = callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... );
	}

	virtual bool isReady ( ) const override {
		return m_data.template is < ReturnType > ( );
	}

	virtual ext::type_index getReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( ReturnType ) );
	}

	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
		if ( isReady ( ) )
			return ext::type_index ( typeid ( getData ( ) ) );
		else
			throw exception::CommonException ( "Runtime type unknown before evaluation." );
	}

	virtual bool cached ( ) const override {
		return isReady ( );
	}
};

template < class ReturnType >
class ValueOperationAbstraction < ReturnType & > : public OperationAbstraction, public ValueProvider < ReturnType & >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
protected:
	virtual ReturnType & getData ( ) const override {
		return m_data.template get < std::reference_wrapper < ReturnType > > ( ).get ( );
	}

	virtual const ReturnType & getConstData ( ) const override {
		return m_data.template get < std::reference_wrapper < ReturnType > > ( ).get ( );
	}

	mutable ext::variant < void, std::reference_wrapper < ReturnType > > m_data;

public:
	template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes >
	inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) )
			m_data = std::reference_wrapper < ReturnType > ( callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... ) );
	}

	template < typename Callable, typename ... Ts, size_t ... Indexes >
	inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) )
			m_data = std::reference_wrapper < ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ) );
	}

	virtual bool isReady ( ) const override {
		return m_data.template is < std::reference_wrapper < ReturnType > > ( );
	}

	virtual ext::type_index getReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( ReturnType ) );
	}

	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
		if ( isReady ( ) )
			return ext::type_index ( typeid ( getData ( ) ) );
		else
			throw exception::CommonException ( "Runtime type unknown before evaluation." );
	}

	virtual bool cached ( ) const override {
		return isReady ( );
	}
};

template < class ReturnType >
class ValueOperationAbstraction < const ReturnType & > : public OperationAbstraction, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
protected:
	virtual const ReturnType & getConstData ( ) const override {
		return m_data.template get < std::reference_wrapper < const ReturnType > > ( ).get ( );
	}

	mutable ext::variant < void, std::reference_wrapper < const ReturnType > > m_data;

public:
	template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes >
	inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) )
			m_data = std::reference_wrapper < const ReturnType > ( callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... ) );
	}

	template < typename Callable, typename ... Ts, size_t ... Indexes >
	inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) )
			m_data = std::reference_wrapper < const ReturnType > ( callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... ) );
	}

	virtual bool isReady ( ) const override {
		return m_data.template is < std::reference_wrapper < const ReturnType > > ( );
	}

	virtual ext::type_index getReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( ReturnType ) );
	}

	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
		if ( isReady ( ) )
			return ext::type_index ( typeid ( getConstData ( ) ) );
		else
			throw exception::CommonException ( "Runtime type unknown before evaluation." );
	}

	virtual bool cached ( ) const override {
		return isReady ( );
	}
};

template < class ReturnType >
class ValueOperationAbstraction < ReturnType && > : public OperationAbstraction, public ValueProvider < ReturnType & >, public ValueProvider < const ReturnType & >, public ValueProvider < ReturnType && >, public ValueProvider < const ReturnType && > {
protected:
	virtual ReturnType & getData ( ) const override {
		return m_data.template get < std::reference_wrapper < ReturnType > > ( ).get ( );
	}

	virtual const ReturnType & getConstData ( ) const override {
		return m_data.template get < std::reference_wrapper < ReturnType > > ( ).get ( );
	}

	mutable ext::variant < void, std::reference_wrapper < ReturnType > > m_data;

public:
	template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes >
	inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) ) {
			ReturnType && res = callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... );
			m_data = std::reference_wrapper < ReturnType > ( res );
		}
	}

	template < typename Callable, typename ... Ts, size_t ... Indexes >
	inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) ) {
			ReturnType && res = callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... );
			m_data = std::reference_wrapper < ReturnType > ( res );
		}
	}

	virtual bool isReady ( ) const override {
		return m_data.template is < std::reference_wrapper < ReturnType > > ( );
	}

	virtual ext::type_index getReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( ReturnType ) );
	}

	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
		if ( isReady ( ) )
			return ext::type_index ( typeid ( getData ( ) ) );
		else
			throw exception::CommonException ( "Runtime type unknown before evaluation." );
	}

	virtual bool cached ( ) const override {
		return isReady ( );
	}
};

template < class ReturnType >
class ValueOperationAbstraction < const ReturnType && > : public OperationAbstraction, public ValueProvider < const ReturnType & >, public ValueProvider < const ReturnType && > {
protected:
	virtual const ReturnType & getConstData ( ) const override {
		return m_data.template get < std::reference_wrapper < const ReturnType > > ( ).get ( );
	}

	mutable ext::variant < void, std::reference_wrapper < const ReturnType > > m_data;

public:
	template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes >
	inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) ) {
			const ReturnType && res = callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... );
			m_data = std::reference_wrapper < const ReturnType > ( res );
		}
	}

	template < typename Callable, typename ... Ts, size_t ... Indexes >
	inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		if ( ! isReady ( ) ) {
			const ReturnType && res = callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... );
			m_data = std::reference_wrapper < const ReturnType > ( res );
		}
	}

	virtual bool isReady ( ) const override {
		return m_data.template is < std::reference_wrapper < const ReturnType > > ( );
	}

	virtual ext::type_index getReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( ReturnType ) );
	}

	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
		if ( isReady ( ) )
			return ext::type_index ( typeid ( getConstData ( ) ) );
		else
			throw exception::CommonException ( "Runtime type unknown before evaluation." );
	}

	virtual bool cached ( ) const override {
		return isReady ( );
	}
};

template < >
class ValueOperationAbstraction < void > : public OperationAbstraction {
public:
	template < typename Callable, typename Object, typename ... Ts, size_t ... Indexes >
	inline void member_run_helper ( Callable callback, const ext::tuple < Object, Ts ... > & inputs, const std::array < bool, 1 + sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		callback ( & std::get < 0 > ( inputs )->getValue ( false ), std::get < Indexes + 1 > ( inputs )->getValue ( std::get < Indexes + 1 > ( moves ) ) ... );
	}

	template < typename Callable, typename ... Ts, size_t ... Indexes >
	inline void run_helper ( Callable callback, const ext::tuple < Ts ... > & inputs, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) const {
		/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
		( void ) inputs;
		( void ) moves;

		callback ( std::get < Indexes > ( inputs )->getValue ( std::get < Indexes > ( moves ) ) ... );
	}

	virtual bool isReady ( ) const override {
		return true;
	}

	virtual ext::type_index getReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( void ) );
	}

	virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
		return ext::type_index ( typeid ( void ) );
	}

	virtual bool cached ( ) const override {
		return false;
	}
};

} /* namespace abstraction */

#endif /* _VALUE_OPERATION_ABSTRACTION_HPP_ */