#include <functional>
#include <type_traits>
#include <cassert>
#include <exception>
#include <iostream>
#include <typeinfo>
#include <utility>
#include <string_view>
#include <string>
#include <queue>
template < typename _Ty, typename...Args >
constexpr inline
void __print_type( void ){
if constexpr ( not ::std::is_function_v< ::std::remove_pointer< _Ty> > ){
auto _Msg = typeid( _Ty ).name();
::std::clog << _Msg << "\t";
if constexpr( sizeof...(Args) ) __print_type< Args... >();
else ::std::endl( ::std::clog );
}else throw ::std::runtime_error("__print_type: met function object");
}
template < typename _Ty, typename...Args >
inline
void print_type( void ){
try{ __print_type< _Ty, Args... >(); }
catch( const ::std::runtime_error& e){
::std::cerr << e.what();
}catch(...){
::std::cerr << "print_type: unknown error";
}
}
class Command{
protected:
::std::string_view _Signature;
public:
Command( void ) = default;
Command( const ::std::string_view& sign )
:_Signature( sign ) {}
virtual ~Command( void ) {}
virtual void execute( void ) = 0;
inline
void SetSignature( const ::std::string_view& sign ){
_Signature = sign;
}
inline
const char * GetSignature( void ) const{
return _Signature.data();
}
void print_log( ::std::ostream& out ) const{
char buf[ 64 ] { 0 };
sprintf( buf,
"Command %s is executing...\n",
_Signature.data() );
out << buf << ::std::endl;
}
};
template < class _Ty >
class Atomic : public Command{
private:
class CallableExcept : public ::std::exception{
private: const char *_Msg { nullptr };
public:
CallableExcept( const char * str )
:_Msg( str ) {}
virtual const char* what( void ) const noexcept{
return _Msg;
}
};
protected:
::std::function< _Ty( void ) > _Action;
_Ty _Result;
public:
Atomic( void ) = default;
template < class _Fn, class...Args >
Atomic( _Fn&& f, Args&&...args ){
try {SetAction( f, args... );}
catch( const CallableExcept& e){
::std::cerr << e.what();
::std::endl( ::std::cerr );
::std::clog.flush();
print_type<_Ty, decltype( f( args... ) )>();
}
catch(...){
::std::cerr << "print_type: unknown error";
}
}
virtual ~Atomic( void ) {}
template < class _Fn, class...Args >
constexpr
void SetAction( _Fn&& f, Args&&...args ){
static_assert( ::std::is_invocable_v< _Fn, Args... > );
if constexpr( not ::std::is_same< _Ty,
typename ::std::result_of< _Fn&&(Args&&...) >::type >
::value )
throw CallableExcept("_Ty and result type of _Fn mismatch");
_Action = ::std::bind( ::std::forward< _Fn >( f ),
::std::forward< Args >( args )... );
}
virtual void execute( void ) override{
Command::print_log( ::std::cout );
auto _FuncWrapper =
[this]{
_Result = _Action();
};
::std::invoke( _FuncWrapper );
}
inline constexpr
const _Ty& GetResult( void ) const noexcept{
return _Result;
}
};
class Macro : public Command{
private:
class HandleCommandExcept : public ::std::exception{
private: const char *_Msg { nullptr };
public:
HandleCommandExcept( const char * str )
:_Msg( str ) {}
virtual const char* what( void ) noexcept{
return _Msg;
}
};
Command *_Cache { nullptr };
::std::queue< Command * > _Aggressive;
public:
Macro( void ) = default;
Macro( const ::std::string_view& sign )
: Command( sign ) {}
virtual void execute( void ) override{
Command::print_log( ::std::cout );
while( !_Aggressive.empty() ) single();
}
inline
void single( void ) noexcept{
( _Aggressive.front() )->execute();
_Aggressive.pop();
}
inline
void pushCommand( Command *command ) noexcept{
_Aggressive.push( command );
}
inline
void undoCommand( void ){
if( _Aggressive.empty() )
throw HandleCommandExcept( "Aggressive commands empty" );
_Aggressive.pop();
}
inline
void redoCommand( void ){
if( !_Cache )
throw HandleCommandExcept( "No cache command buffered" );
pushCommand( _Cache );
_Cache = nullptr;
}
};
int main( void ){
Atomic< int > Add( [](const int& a,
const int& b)->int{
return a + b;
}, 2, 3 );
Add.SetSignature("Calculate 2+3");
Atomic< double > Div( []( const int& a,
const int& b)->double{
return ( double )a/b;
}, 2, 3);
Div.SetSignature("Calculate 2/3");
Atomic< int > Mul( []( const int& a,
const int& b)->int{
return a* b;
}, 2, 3);
Mul.SetSignature("Calculate 2*3");
Macro Complex("Complex");
Complex.pushCommand( &Add );
Complex.pushCommand( &Div );
Complex.SetSignature("Macro : Agressiate Atomic Add & Div");
Macro Root("Root");
Root.pushCommand( &Mul );
Root.pushCommand( &Complex );
Root.SetSignature("Macro : Agressiate Atomic Mul and Macro Complex");
Root.execute();
::std::cout << "Atomic Add result:\t"
<< Add.GetResult();
::std::endl( ::std::cout );
::std::cout << "Atomic Div result:\t"
<< Div.GetResult();
::std::endl( ::std::cout );
::std::cout << "Atomic Mul result:\t"
<< Mul.GetResult();
::std::endl( ::std::cout );
return 0;
}
【设计模式:command pattern】
最新推荐文章于 2024-05-30 16:11:34 发布