Newer
Older
/*
* WrapperAbstraction.hpp
*
* Created on: 11. 7. 2017
* Author: Jan Travnicek
*/
#ifndef _WRAPPER_ABSTRACTION_HPP_
#define _WRAPPER_ABSTRACTION_HPP_
#include <abstraction/OperationAbstraction.hpp>
namespace abstraction {
template < class ... ParamTypes >
class WrapperAbstraction : public OperationAbstraction {
std::function < std::shared_ptr < OperationAbstraction > ( ParamTypes ... ) > m_WrapperFinder;
ext::variant < void, std::shared_ptr < OperationAbstraction > > m_data;
protected:
ext::tuple < std::shared_ptr < ValueProvider < ParamTypes > > ... > m_params;
std::array < bool, sizeof ... ( ParamTypes ) > m_moves;
public:
WrapperAbstraction ( std::function < std::shared_ptr < OperationAbstraction > ( ParamTypes ... ) > wrapperFinder ) : m_WrapperFinder ( wrapperFinder ) {
for ( unsigned i = 0; i < sizeof ... ( ParamTypes ); ++ i )
m_moves [ i ] = false;
}
private:
virtual bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, unsigned index, bool move ) override {
if ( index >= m_moves.size ( ) )
throw std::invalid_argument ( "Parameter index " + ext::to_string ( index ) + " out of bounds.");
auto attachCallback = [ & ] ( auto & param ) {
if ( param != nullptr )
return false;
typename std::decay < decltype ( param )>::type validData = std::dynamic_pointer_cast < typename std::decay < decltype ( param ) >::type::element_type > ( input->getProxyAbstraction ( ) );
if ( validData ) {
m_moves [ index ] = move;
param = validData;
return true;
} else {
return false;
}
};
return ext::call_on_nth < bool > ( m_params, index, attachCallback );
}
virtual bool detachInput ( unsigned index ) override {
if ( index >= m_moves.size ( ) )
throw std::invalid_argument ( "Parameter index " + ext::to_string ( index ) + " out of bounds.");
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
m_moves [ index ] = false;
auto detachCallback = [ & ] ( auto & param ) {
param = nullptr;
return true;
};
return ext::call_on_nth < bool > ( m_params, index, detachCallback );
}
public:
virtual bool inputsReady ( ) const override {
auto readyCallback = [ ] ( const auto & param ) {
return ( bool ) param && param->isReady ( );
};
return ext::all_of ( m_params, readyCallback );
}
virtual bool inputsAttached ( ) const override {
auto attachedCallback = [ ] ( const auto & param ) {
return ( bool ) param;
};
return ext::all_of ( m_params, attachedCallback );
}
private:
template < typename ... Ts, size_t ... Indexes >
inline void finder_helper ( const ext::tuple < Ts ... > & params, const std::array < bool, sizeof ... ( Indexes ) > moves, std::index_sequence < Indexes ... > ) {
/* make unused parameter warning go away in case of sizeof ... ( Ts ) == 0 */
( void ) params;
( void ) moves;
m_data = m_WrapperFinder ( std::get < Indexes > ( params )->getValue ( std::get < Indexes > ( moves ) ) ... );
}
public:
virtual bool run ( ) override {
if ( m_data.is < void > ( ) )
this->finder_helper ( this->m_params, this->m_moves, std::make_index_sequence < sizeof ... ( ParamTypes ) > { } );
auto getParam = [ & ] ( auto & param ) {
return std::dynamic_pointer_cast < abstraction::OperationAbstraction > ( param );
};
std::shared_ptr < OperationAbstraction > abstraction = m_data.template get < std::shared_ptr < OperationAbstraction > > ( );
for ( unsigned index = 0; index < sizeof ... ( ParamTypes ); ++ index )
abstraction->attachInput ( ext::call_on_nth < std::shared_ptr < abstraction::OperationAbstraction > > ( m_params, index, getParam ), index, m_moves [ index ] );
}
virtual bool eval ( ) override {
if ( ! inputsAttached ( ) )
return false;
if ( this->cached ( ) )
return true;
auto evalCallback = [ ] ( const auto & param ) {
return param->eval ( );
};
if ( ! ext::all_of ( m_params, evalCallback ) )
return false;
return this->run ( );
}
virtual unsigned numberOfParams ( ) const override {
return sizeof ... ( ParamTypes );
}
return m_data.template is < std::shared_ptr < OperationAbstraction > > ( ) && m_data.template get < std::shared_ptr < OperationAbstraction > > ( )->isReady ( );
}
virtual bool cached ( ) const override {
return isReady ( );
}
virtual ext::type_index getParamTypeIndex ( unsigned index ) const override {
auto callback = [ & ] ( auto & param ) {
return ext::type_index ( typeid ( typename std::decay < decltype ( param ) >::type::element_type::return_type ) );
};
return ext::call_on_nth < ext::type_index > ( m_params, index, callback );
}
virtual ext::type_index getReturnTypeIndex ( ) const override {
return getRuntimeReturnTypeIndex ( );
}
virtual ext::type_index getRuntimeReturnTypeIndex ( ) const override {
if ( isReady ( ) )
return m_data.template get < std::shared_ptr < OperationAbstraction > > ( )->getProxyAbstraction ( )->getRuntimeReturnTypeIndex ( );
else
throw std::domain_error ( "Runtime type unknown before evaluation." );
}
virtual std::shared_ptr < abstraction::OperationAbstraction > getProxyAbstraction ( ) override {
if ( isReady ( ) )
return m_data.template get < std::shared_ptr < OperationAbstraction > > ( )->getProxyAbstraction ( );
else
throw std::domain_error ( "Runtime type unknown before evaluation." );
}
};
} /* namespace abstraction */
#endif /* _WRAPPER_ABSTRACTION_HPP_ */