Boost 1.55 버전 기준으로 작성했습니다.
#pragma once
//#include <boost/mpl/aux_/test.hpp>
#include <vector>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <iostream>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/list_c.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/prior.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/remove.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/equal_to.hpp>
namespace mpl = boost::mpl;
using namespace std;
//MPL_TEST_CASE()
//{
// MPL_ASSERT( (boost::is_same<char, char> ) );
//}
template< typename T, typename U >
struct is_same_another : boost::integral_constant< bool, false >
{
typedef ::boost::integral_constant< bool, false > base_;
using base_::value;
};
template< typename T >
struct is_same_another< T, T > : boost::integral_constant< bool, true >
{
typedef ::boost::integral_constant< bool, true > base_;
using base_::value;
};
void mpl_test()
{
// is same
{
std::cout << "is_same_another<bool,bool>::value; " << is_same_another< bool, bool >::value << std::endl;
std::cout << "is_same_another<bool,int>::value; " << is_same_another< bool, int >::value << std::endl;
}
//typedef mpl::push_back< int, mpl::integral_c< 100 > >::type push_back_test;
// vector c 테스트
// at_c 에서 뽑아온다.
{
typedef mpl::vector_c< int, 0, 2, 4, 6, 8 > container1;
cout << "----------------------------------------------" << endl;
cout << "mpl::vector_c, mpl::at_c 테스트" << endl;
cout << "----------------------------------------------" << endl;
cout << mpl::at_c< container1, 0 >::type::value << endl;
cout << mpl::at_c< container1, 1 >::type::value << endl;
cout << mpl::at_c< container1, 2 >::type::value << endl;
cout << mpl::at_c< container1, 3 >::type::value << endl;
cout << mpl::at_c< container1, 4 >::type::value << endl;
}
// 사이즈를 구하는 함수 mpl::size
// vector_c size
{
cout << "----------------------------------------------" << endl;
cout << "mpl::size 테스트" << endl;
cout << "----------------------------------------------" << endl;
typedef mpl::vector_c< int, 0, 2 > container1;
typedef mpl::vector_c< int, 0, 2, 4 > container2;
typedef mpl::vector_c< int, 0, 2, 4, 8 > container3;
typedef mpl::vector_c< int, 0, 2, 4, 8, 10 > container4;
cout << mpl::size< container1 >::value << endl;
cout << mpl::size< container2 >::type::value << endl;
cout << mpl::size< container3 >::value << endl;
cout << mpl::size< container4 >::value << endl;
}
// mpl::front - 첫번째 요소의 값을 구한다. mpl::back은 mpl::list 에서 적용 불가
{
cout << "----------------------------------------------" << endl;
cout << "mpl::list_c, mpl::front 테스트" << endl;
cout << "----------------------------------------------" << endl;
typedef mpl::list_c< int, 0, 1 > container1;
typedef mpl::list_c< int, 1, 2 > container2;
typedef mpl::list_c< int, 2, 3 > container3;
typedef mpl::list_c< int, 3, 4 > container4;
cout << mpl::front< container1 >::type::value << endl;
cout << mpl::front< container2 >::type::value << endl;
cout << mpl::front< container3 >::type::value << endl;
cout << mpl::front< container4 >::type::value << endl;
}
{
cout << "----------------------------------------------" << endl;
cout << "mpl::begin, mpl::next, mpl::deref, mpl::end 테스트" << endl;
cout << "----------------------------------------------" << endl;
typedef mpl::vector_c< int, 2, 4, 6, 8 > container1;
typedef mpl::begin< container1 >::type it1;
typedef mpl::next< it1 >::type it2;
typedef mpl::next< it2 >::type it3;
typedef mpl::next< it3 >::type it4;
cout << mpl::deref< it1 >::type::value << endl;
cout << mpl::deref< it2 >::type::value << endl;
cout << mpl::deref< it3 >::type::value << endl;
cout << mpl::deref< it4 >::type::value << endl;
typedef mpl::end< container1 >::type ie;
cout << "end ? - " << boost::is_same< ie, it4 >::value << endl;
typedef mpl::next< it4 >::type it5;
cout << "end ? - " << boost::is_same< ie, it5 >::value << endl;
}
{
cout << "----------------------------------------------" << endl;
cout << "mpl::prior 테스트, vector_c에서만 사용 가능" << endl;
cout << "----------------------------------------------" << endl;
typedef mpl::vector_c< int, 2, 4, 6, 8 > container1;
typedef mpl::end< container1 >::type itE;
typedef mpl::begin< container1 >::type itB;
typedef mpl::prior< itE >::type it4;
typedef mpl::prior< it4 >::type it3;
typedef mpl::prior< it3 >::type it2;
typedef mpl::prior< it2 >::type it1;
cout << mpl::deref<it1>::type::value << endl;
cout << mpl::deref<it2>::type::value << endl;
cout << mpl::deref<it3>::type::value << endl;
cout << mpl::deref<it4>::type::value << endl;
}
{
cout << "----------------------------------------------" << endl;
cout << "mpl::empty 테스트" << endl;
cout << "----------------------------------------------" << endl;
typedef mpl::vector_c< int, 2, 4, 6, 8 > container1;
typedef mpl::vector_c< int, 1 > container2;
typedef mpl::vector_c< int > container3;
cout << mpl::empty<container1>::type::value << endl;
cout << mpl::empty<container2>::type::value << endl;
cout << mpl::empty<container3>::type::value << endl;
}
// mpl::push_front, push_back - mpl::list 는 mpl::push_back 을 사용하지 못한다.
{
cout << "----------------------------------------------" << endl;
cout << "mpl::push_front 테스트" << endl;
cout << "----------------------------------------------" << endl;
typedef mpl::vector_c< int > container1_0;
typedef mpl::vector_c< int, 8, 6, 4, 2 > container3;
typedef mpl::push_front< container1_0, mpl::int_<2> >::type container1_1;
typedef mpl::push_front< container1_1, mpl::int_<4> >::type container1_2;
typedef mpl::push_front< container1_2, mpl::int_<6> >::type container1_3;
typedef mpl::push_front< container1_3, mpl::int_<8> >::type container1_4;
cout << mpl::at_c<container1_4, 0>::type::value << endl;
cout << mpl::at_c<container1_4, 1>::type::value << endl;
cout << mpl::at_c<container1_4, 2>::type::value << endl;
cout << mpl::at_c<container1_4, 3>::type::value << endl;
// 같은값은 아니다.
cout << "is same ? - " << boost::is_same< container1_4, container3 >::value << endl;
// mpl::equal 로 비교하면 같은값이 아니자나
cout << "is equal ? - " << mpl::equal< container1_4, container3 >::value << endl;
}
// mpl::push_front, push_back - mpl::list 는 mpl::push_back 을 사용하지 못한다.
{
cout << "----------------------------------------------" << endl;
cout << "mpl::remove 테스트" << endl;
cout << "----------------------------------------------" << endl;
// vector_c에서는 mpl::remove 가 적용되지 않는다.
typedef mpl::vector_c< int, 2, 2, 6, 8 > container1;
typedef mpl::remove< container1, mpl::int_<2> >::type container1_68;
cout << mpl::at_c<container1_68, 0>::type::value << endl;
cout << mpl::at_c<container1_68, 1>::type::value << endl;
cout << mpl::at_c<container1_68, 2>::type::value << endl;
cout << mpl::at_c<container1_68, 3>::type::value << endl;
// vector 에서는 mpl::remove 가 적용된다.
typedef mpl::vector< int, float, float, int > container2;
typedef mpl::vector< int, int > container3;
typedef mpl::remove< container2, float >::type container2_int;
cout << "equal? - " << mpl::equal< container2_int, container3 >::type::value << endl;
cout << typeid( mpl::at_c< container2_int, 0 >::type ).name() << endl;
cout << typeid( mpl::at_c< container2_int, 1 >::type ).name() << endl;
cout << typeid( mpl::at_c< container2_int, 2 >::type ).name() << endl;
// 컴파일 에러!
//cout << typeid( mpl::at_c< container2_int, 3 >::type ).name() << endl;
}
{
cout << "----------------------------------------------" << endl;
cout << "mpl:: 테스트" << endl;
cout << "----------------------------------------------" << endl;
// 자리값을 이용해 -3, 3 의 결과물이 나온다.
cout << mpl::apply< mpl::minus< mpl::_1, mpl::_2 >, mpl::int_<1>, mpl::int_<4> >::type::value << std::endl;
cout << mpl::apply< mpl::minus< mpl::_2, mpl::_1 >, mpl::int_<1>, mpl::int_<4> >::type::value << std::endl;
// unnamed placeholder( mpl::_ = 이름없는 자리표 ) 는 "순서대로 알아서 인수를 맵핑시켜달라" 라는 의미로 해석
cout << mpl::apply< mpl::plus< mpl::_, mpl::_ >, mpl::int_<1>, mpl::int_<4> >::type::value << std::endl;
cout << mpl::apply< mpl::plus< mpl::_, mpl::_ >, mpl::int_<4>, mpl::int_<1> >::type::value << std::endl;
// unnamed placeholder 가 2개라면 인수도 2개여야 한다. 그래서 이것은 에러!
// cout << mpl::apply< mpl::plus< mpl::_, mpl::_ >, mpl::int_<4> >::type::value << std::endl;
// 인수는 하나이지만 placeholder를 이용해서 컴파일이 가능하다.
cout << mpl::apply< mpl::plus< mpl::_1, mpl::_1 >, mpl::int_<4> >::type::value << std::endl;
}
}
// Meta Function class
// 공개적으로 접근 가능한 apply 라는 메타 함수를 내포한 클래스
// 1. apply 의 내부에 기능을 직접 구현한 메타함수 클래스
struct MetaFuncClass_Plus
{
// apply 라는 메타 함수가 즉 표현식이 된다
template< typename T1, typename T2 >
struct apply
{
typedef typename mpl::plus< T1, T2 >::type type;
};
};
// 2. 상속을 통한 메타함수 클래스
struct MetaFuncForwarding_Plus
{
template< typename T1, typename T2 >
struct apply : mpl::plus< T1, T2 >
{
};
};
// mpl::apply 함수
// mpl 에서는 자리표 표현식과 메타함수 클래스를 Lambda Expression ( 람다 표현식 ) 이라고 합니다.
// 이는 둘다 apply 를 통하여 재평가 될 수 있다는 것을 위의 두 예제에서 보셨을 겁니다.
// mpl::apply< 첫번째 인수, 두번째, 세번째 >
// 위의 mpl::apply 함수는 첫번째 인수를 호출하는 메타함수이며, 첫번째 인수는 lambda Expression 이어야 합니다.
// 이를 적절히 호출하기 위해서는 람다표현식에 적용할 인수들( 두번째, 세번째 , ... )과 함꼐 호출되어져야 합니다.
void meta_test2()
{
cout << mpl::apply< MetaFuncClass_Plus, mpl::int_<2>, mpl::int_<3> >::type::value << std::endl;
cout << mpl::apply< MetaFuncForwarding_Plus, mpl::int_<2>, mpl::int_<3> >::type::value << std::endl;
}
// mpl::lambda 함수
template< typename N1, typename N2 >
struct my_plus
{
typedef mpl::integral_c< long, N1::value + N2::value > type;
};
struct print_list
{
template< class T >
void operator()( T a ) const
{
cout << a << "-";
}
};
#define TEST7
void meta_test3()
{
typedef mpl::list_c< long, 0, 2, 4, 6, 8, 10 > evens;
typedef mpl::list_c< long, 2, 3, 5, 7, 11, 13 > primes;
typedef mpl::list_c< long, 2, 5, 9, 13, 19, 23 > sums;
#ifdef TEST1
typedef mpl::transform< evens, primes, mpl::plus<> >::type result;
#endif
#ifdef TEST2
typedef mpl::transform< evens, primes, MetaFuncClass_Plus >::type result;
#endif
#ifdef TEST3
typedef mpl::transform< evens, primes, MetaFuncForwarding_Plus >::type result;
#endif
#ifdef TEST4
typedef mpl::transform< evens, primes, mpl::plus< mpl::_1, mpl::_2 > >::type result;
#endif
#ifdef TEST5
typedef mpl::transform< evens, primes, mpl::plus< mpl::_, mpl::_ > >::type result;
#endif
#ifdef TEST6
typedef mpl::transform< evens, primes, my_plus< mpl::_1, mpl::_2 > >::type result;
#endif
#ifdef TEST7
typedef mpl::transform< evens, primes, mpl::lambda< my_plus< mpl::_, mpl::_ > > >::type result;
#endif
mpl::for_each< result >( print_list() );
cout << endl;
mpl::for_each< sums >( print_list() );
cout << endl;
// 타입과 값 모두 체크
cout << "Equal? - " << mpl::equal< result, sums >::type::value << endl;
// 값들만 체크
cout << "Equal To? - " << mpl::equal< result, sums, mpl::equal_to< mpl::_1, mpl::_2 > >::type::value << std::endl;
}
template< class T >
struct foo_one
{
typedef T type;
};
template< class T >
struct foo_two
{
typedef typename foo_one<T>::type type;
};
template< class T >
struct foo_three
{
typedef typename foo_two<T>::type type;
};
void mpl_test4()
{
typedef foo_three<long>::type foo_three_of_type;
cout << typeid( foo_three_of_type ).name() << endl;
}
#define STD_OUT( a ) std_out(#a, typeid( a ).name() )
void std_out( const char* type_data, const char* type_name )
{
cout << "* TYPE_DATA - " << type_data << endl;
cout << "* TYPE_NAME - " << type_name << endl;
cout<< endl << endl;
}
// 적절한 방법으로 지연평가를 수행함
void test_one()
{
typedef std::vector< mpl::_ > vec_lambda;
STD_OUT( vec_lambda );
typedef mpl::lambda< vec_lambda >::type vec_mata_func;
STD_OUT( vec_mata_func );
typedef mpl::apply< vec_lambda, int >::type::iterator vec_int_iterator;
STD_OUT( vec_int_iterator );
}
// 템플릿 인스턴스화가 되고 나서 지연평가 apply 를 수행함
void test_two()
{
typedef std::vector< mpl::_ >::iterator vec_it_lambda;
STD_OUT( vec_it_lambda );
typedef mpl::lambda< vec_it_lambda >::type vec_it_meta_func;
STD_OUT( vec_it_meta_func );
}
void mpl_test5()
{
test_one();
test_two();
}
Boost Optional 샘플 (0) | 2016.01.31 |
---|---|
Multi Index 샘플 (0) | 2016.01.31 |
Boost Meta State Machine 테스트 2 (0) | 2016.01.29 |
Boost Meta State Machine 테스트 (0) | 2016.01.29 |
Boost lock-free Queue 성능 테스트 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace boost::msm::front;
// 이벤트들
struct play {};
struct end_pause{};
struct stop{};
struct pause {};
struct open_close {};
struct NextSong {};
struct PreviousSong {};
struct error_found {};
struct end_error {};
struct end_error2 {};
// 플래그, 현재 상태의 property에 관한 정보를 허용한다.
struct PlayingPaused {};
struct CDLoaded {};
struct FirstSongPlaying {};
// 약간의 데이터를 전달하는 완료된 이벤트 타입
struct cd_detected
{
cd_detected( std::string _name ) : name( _name )
{}
std::string name;
};
// front-end 로 정의돈 FSM 구조체
struct player_ : public msm::front::state_machine_def< player_ >
{
typedef int activate_deferred_events;
//
// FSM 상태들.
struct Empty : public msm::front::state<>
{
// 플레이 이벤트가 이 상태를 떠나면, 그 플레이 상태가 처리 되거나 또는 거부 될때까지 지연된다
//typedef mpl::vector<play> deferred_events;
// 모든(선택적인) entry/exit 함수는 전달된 이벤트를 갖는다.
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 빈 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 빈 상태" << std::endl; }
};
struct Open : public msm::front::state<>
{
// 플레이 이벤트가 이 상태를 떠나면, 그 플레이 상태가 처리 되거나 또는 거부 될때까지 지연된다
//typedef mpl::vector<play> deferred_events;
typedef mpl::vector1<CDLoaded> flag_list;
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 열린 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 열린 상태" << std::endl; }
};
struct Stopped : public msm::front::state<>
{
// 플레이 이벤트가 이 상태를 떠나면, 그 플레이 상태가 처리 되거나 또는 거부 될때까지 지연된다
typedef mpl::vector1<CDLoaded> flag_list;
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 정지된 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 정지된 상태" << std::endl; }
};
// 플레이어 상태 머신에 포함된 상태는 스스로 그러한 상태 머신이 된다.
// 당신이 보는것처럼, 플레잉은 따로 선언이 필요 없이
// 어디에서든 다른팀의 다른 모듈로 따로따로 개발되어질수 있다.
// 이것은 내가 간단히 plyaer 내부에 정의했다.
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
// 플레이 중일때, cd 는 로딩완료되었고, 우리는 일시정지 또는 플레잉안에 있다.
typedef mpl::vector2< PlayingPaused, CDLoaded > flag_list;
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 플레이중 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 플레이중 상태" << std::endl; }
// FSM 상태 리스트들
struct Song1 : public msm::front::state<>
{
typedef mpl::vector1< FirstSongPlaying > flag_list;
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 첫번째 노래 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 첫번째 노래 상태" << std::endl; }
};
struct Song2 : public msm::front::state<>
{
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 두번째 노래 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 두번째 노래 상태" << std::endl; }
};
struct Song3 : public msm::front::state<>
{
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: 세번째 노래 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: 세번째 노래 상태" << std::endl; }
};
// 초기화 상태는 반드시 정의되야 함
typedef Song1 initial_state;
//
// 전이 행동들
void start_next_song( NextSong const& ) { std::cout << "재생중:다음곡 재생 시작" << std::endl; }
void start_prev_song( PreviousSong const& ) { std::cout << "재생중:이전곡 재생 시작" << std::endl; }
//
// 방어 조건들
//
// 전이 테이블을 쉽게 만들기 위해 typedef
typedef Playing_ pl;
// Playing_을 위한 전이 테이블
struct transition_table : mpl::vector4
<
// 시작, 이벤트, 다음, 전이 행동, 방어행동
// +-------------------+-------------------+-------------------+--------------------------+----------------+
a_row< Song1 , NextSong , Song2 , &pl::start_next_song >,
a_row< Song2 , PreviousSong , Song1 , &pl::start_prev_song >,
a_row< Song2 , NextSong , Song3 , &pl::start_next_song >,
a_row< Song3 , PreviousSong , Song2 , &pl::start_prev_song >
> {};
// 기본 no-transition 응답을 재정의
template< class FSM, class Event >
void no_transition( Event const& e, FSM&, int state )
{
std::cout << "no_transition from state " << state << " on evert" << typeid(e).name() << std::endl;
}
};
// back-end( 실질적인 인스턴스를 생성하는 것 )
typedef msm::back::state_machine< Playing_ > Playing;
// entry/exit 를 정의하지 않는 상태
struct Paused : public msm::front::state<>
{
typedef mpl::vector2< PlayingPaused, CDLoaded > flag_list;
};
// all ok
struct AllOK : public msm::front::state<>
{
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: All OK 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: All OK 상태" << std::endl; }
};
// 이 상태는 모든 이벤트가 막혔을 때 가게되는 만들어진 종점 상태이다.
struct ErrorMode : public msm::front::interrupt_state< end_error > // 에러모드는 중단 뿐이 없다. 되돌리려면 end_error 이벤트를 발생시킨다.
{
template< class Event, class FSM >
void on_entry(Event const&, FSM&) { std::cout << "입장: ErrorMode 상태" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const& , FSM& ) { std::cout << "퇴장: ErrorMode 상태" << std::endl; }
};
// player 상태 머신의 초기화 상태
typedef mpl::vector< Empty, AllOK > initial_state;
// 전이 행돌들
void start_playback( play const& ) { std::cout << "CD 플레이어: 재생 시작" << std::endl; }
void open_drawer( open_close const& ) { std::cout << "CD 플레이어: CD drawer 열기" << std::endl; }
void close_drawer( open_close const& ) { std::cout << "CD 플레이어: CD drawer 닫기" << std::endl; }
void store_cd_info( cd_detected const& ) { std::cout << "CD 플레이어: CD 정보 읽기" << std::endl; }
void stop_playback( stop const& ) { std::cout << "CD 플레이어: 재생 중지" << std::endl; }
void pause_playback( pause const& ) { std::cout << "CD 플레이어: 재생 일시 정지" << std::endl; }
void resume_playback( end_pause const& ) { std::cout << "CD 플레이어: 다시 재생" << std::endl; }
void stop_and_open( open_close const& ) { std::cout << "CD 플레이어: 정지 후 CD drawer 열기" << std::endl; }
void stopped_again( stop const& ) { std::cout << "CD 플레이어: 다시 정지" << std::endl; }
void report_error( error_found const& ) { std::cout << "CD 플레이어: 문제 발생 알림" << std::endl; }
void report_end_error( end_error const& ) { std::cout << "CD 플레이어: 문제 종료 알림" << std::endl; }
// 전이 테이플 편하게 할라꼬
typedef player_ p;
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +--------------+------------------+----------------+------------------------+------------------------+
// 정지 상태
a_row < Stopped, play, Playing, &p::start_playback >,
a_row < Stopped, open_close, Open, &p::open_drawer >,
a_row < Stopped, stop, Stopped, &p::stopped_again >,
// +--------------+------------------+----------------+------------------------+------------------------+
// 열림 상태
a_row < Open, open_close, Empty, &p::close_drawer >,
Row < Open, play, none, Defer, none >,
// +--------------+------------------+----------------+------------------------+------------------------+
// 빈 상태
a_row < Empty, open_close, Open, &p::open_drawer >,
a_row < Empty, cd_detected, Stopped, &p::store_cd_info >,
Row < Empty, play, none, Defer, none >,
// +--------------+------------------+----------------+------------------------+------------------------+
// 재생 상태
a_row < Playing, stop, Stopped, &p::stop_playback >,
a_row < Playing, pause, Paused, &p::pause_playback >,
a_row < Playing, open_close, Open, &p::stop_and_open >,
// +--------------+------------------+----------------+------------------------+------------------------+
// 일지 정시 상태
a_row < Paused, end_pause, Playing, &p::resume_playback >,
a_row < Paused, stop, Stopped, &p::stop_playback >,
a_row < Paused, open_close, Open, &p::stop_and_open >,
// +--------------+------------------+----------------+------------------------+------------------------+
// 일지 정시 상태
a_row < AllOK, error_found, ErrorMode, &p::report_error >,
a_row < ErrorMode, end_error, AllOK, &p::report_end_error >
>{};
// 기본 no-transition 응답을 재정의
template< class FSM, class Event >
void no_transition( Event const& e, FSM&, int state )
{
std::cout << "no_transition from state " << state << " on evert" << typeid(e).name() << std::endl;
}
};
// back-end 를 뽑아내자
typedef msm::back::state_machine< player_ > player_state_machine;
static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused", "AllOK", "ErrorMode" };
void pstate(player_state_machine const& p)
{
for( unsigned int i = 0; i < player_state_machine::nr_regions::value; ++i )
{
std::cout << " -> " << state_names[ p.current_state()[i] ] << std::endl;
}
}
void msm_test()
{
player_state_machine psm;
// 고수준 상태 머신은 시작이 필요하단다. 이것은 on_entry와 상태 머신의 시작의 mark를 호출 할것이다.
psm.start();
std::cout << std::endl;
// 지연된 이벤트 테스트
// 무조건 cd_detected 이후에 처리되야 하는 empty 와 open안에서 지연됨
psm.process_event( play() );
// 플래그 테스트
std::cout << "CDLoaded active:" << std::boolalpha << psm.is_flag_active< CDLoaded >() << std::endl; // -> 실패 ( 여전히 CD가 없다. )
// 열기로 가자, empty의 on_exit 가 호출되고, 그리고 행동, 그리고 open의 on_entry가 호출된다.
psm.process_event( open_close() ); pstate( psm );
psm.process_event( open_close() ); pstate( psm );
psm.process_event( cd_detected( "louie, louie" ) );
//psm.process_event( cd_detected( "louie, louie" ) );
//psm.process_event( play() );
// 이 시점에, play는 active( 지연되었던 )??
std::cout << "PlayingPaused active:" << std::boolalpha << psm.is_flag_active< PlayingPaused >() << std::endl;
std::cout << "FirstSong active:" << std::boolalpha << psm.is_flag_active< FirstSongPlaying >() << std::endl;
psm.process_event( NextSong() ); pstate( psm );
std::cout << std::endl;
psm.stop();
printf( "end msm test... (press enter)\n" );
getchar();
}
Multi Index 샘플 (0) | 2016.01.31 |
---|---|
Boost MPL 샘플 (0) | 2016.01.29 |
Boost Meta State Machine 테스트 (0) | 2016.01.29 |
Boost lock-free Queue 성능 테스트 (0) | 2016.01.29 |
Boost Fusion 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
// back
#include <boost/msm/back/state_machine.hpp>
// front
#include <boost/msm/front/state_machine_def.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace
{
// 이벤트들
struct play {};
struct end_pause {};
struct stop {};
struct pause {};
struct open_close {};
struct NextSong {};
struct PreviousSong {};
// 디스크 타입
// 약간의 데이터를 전송하는 복잡한 이벤트 타입
enum DiskTypeEnum
{
DISK_CD = 0,
DISK_DVD = 1,
};
struct cd_detected
{
cd_detected( std::string _name, DiskTypeEnum _diskType )
: name_( _name )
, diskType_ ( _diskType )
{
}
std::string name_;
DiskTypeEnum diskType_;
};
// front-end : FSM 구조체를 정의
struct player_ : public msm::front::state_machine_def< player_ >
{
// 입장
template< class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "entering: Player" << std::endl; }
// 퇴장
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "leaving: Player" << std::endl; }
// the list of fsm states
struct Empty : public msm::front::state<>
{
template < class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "entering: Empty" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "leaving: Empty" << std::endl; }
};
struct Open : public msm::front::state<>
{
template < class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "entering: Open" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "leaving: Open" << std::endl; }
};
struct Stopped : public msm::front::state<msm::front::default_base_state,msm::front::sm_ptr>
{
template < class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "entering: Stopped" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "leaving: Stopped" << std::endl; }
void set_sm_ptr( player_* pl )
{
m_player = pl;
}
player_* m_player;
};
struct Paused : public msm::front::state<>
{
template < class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "entering: Paused" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "leaving: Paused" << std::endl; }
};
struct Playing_ : public msm::front::state_machine_def<Playing_>
{
template < class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "entering: Playing" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "leaving: Playing" << std::endl; }
struct Song1 : public msm::front::state<>
{
template< class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "starting: First Song" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "finishing: First Song" << std::endl; }
};
struct Song2 : public msm::front::state<>
{
template< class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "starting: Second Song" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "finishing: Second Song" << std::endl; }
};
struct Song3 : public msm::front::state<>
{
template< class Event, class FSM >
void on_entry( Event const&, FSM& ) { std::cout << "starting: Third Song" << std::endl; }
template< class Event, class FSM >
void on_exit( Event const&, FSM& ) { std::cout << "finishing: Third Song" << std::endl; }
};
typedef Song1 initial_state;
// 전이 함수들
void start_next_song( NextSong const& ) { std::cout << "Playing::start_next_song" << std::endl; }
void start_prev_song( PreviousSong const& ) { std::cout << "Playing::start_prev_song" << std::endl; }
// 가드 조건
typedef Playing_ pl;
// 플레잉의 전이 테이블
struct transition_table : mpl::vector4
<
a_row < Song1, NextSong, Song2, &pl::start_next_song >,
a_row < Song2, PreviousSong, Song1, &pl::start_prev_song >,
a_row < Song2, NextSong, Song3, &pl::start_next_song >,
a_row < Song3, PreviousSong, Song2, &pl::start_prev_song >
>{};
// 없는 전이 상태
template< class FSM, class Event >
void no_transition( Event const& e, FSM&, int state)
{
std::cout << "no transition state" << state << " on event" << typeid(e).name() << std::endl;
}
};
// back-end
typedef msm::back::state_machine<Playing_> Playing;
// 플레이어 스테이트 머신의 초기 상태, 반드시 정의되어야 한다.
typedef Empty initial_state;
// 전의되는 행동들.
void start_playback( play const& ) { std::cout << "player::start_playback" << std::endl; }
void open_drawer( open_close const& ) { std::cout << "player::open_drawer" << std::endl; }
void close_drawer( open_close const& ) { std::cout << "player::close_drawer" << std::endl; }
void store_cd_info( cd_detected const& ) { std::cout << "player::store_cd_info" << std::endl; }
void stop_playback( stop const& ) { std::cout << "player::stop_playback" << std::endl; }
void pause_playback( pause const& ) { std::cout << "player::pause_playback" << std::endl; }
void resume_playback( end_pause const& ) { std::cout << "player::resume_playback" << std::endl; }
void stop_and_open( open_close const& ) { std::cout << "player::stop_and_open" << std::endl; }
void stopped_again( stop const& ) { std::cout << "player::stopped_again" << std::endl; }
// 가드 조건? 실행 불가 조건을 얘기하는듯
bool good_disk_format( cd_detected const& evt )
{
// 방어 조건 테스트, cd만 가능, dvd 안됨
if( evt.diskType_ != DISK_CD )
{
std::cout << "wrong disk, sorry" << std::endl;
return false;
}
return true;
}
bool auto_start(cd_detected const& )
{
return false;
}
typedef player_ p; // 전의 테이블을 깔끔하게 만들기 위해서
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +--------------+------------------+----------------+------------------------+------------------------+
// 정지 상태
a_row < Stopped, play, Playing, &p::start_playback >,
a_row < Stopped, open_close, Open, &p::open_drawer >,
_row < Stopped, stop, Stopped >,
// 열림 상태
a_row < Open, open_close, Empty, &p::close_drawer >,
// 빈 상태
a_row < Empty, open_close, Open, &p::open_drawer >,
row < Empty, cd_detected, Stopped, &p::store_cd_info, &p::good_disk_format >,
row < Empty, cd_detected, Playing, &p::store_cd_info, &p::auto_start >,
// 재생 상태
a_row < Playing, stop, Stopped, &p::stop_playback >,
a_row < Playing, pause, Paused, &p::pause_playback >,
a_row < Playing, open_close, Open, &p::stop_and_open >,
// 일지 정시 상태
a_row < Paused, end_pause, Playing, &p::resume_playback >,
a_row < Paused, stop, Stopped, &p::stop_playback >,
a_row < Paused, open_close, Open, &p::stop_and_open >
>{};
// 없는 전이 상태
template< class FSM, class Event >
void no_transition( Event const& e, FSM& , int state)
{
std::cout << "no transition state" << state << " on event" << typeid(e).name() << std::endl;
}
// row : 5개의 매개변수를 가진다. 시작 상태, 이벤트, 목표 상태, 행동( 상태 전의가 성공했을때 호출 함수) 그리고 방어( 상태 전의가 가능한지 확인 함수)
// a_row : a는 행동을 뜻하며, 방어를 빼고 액션만 허용
// g_row : g는 방어를 뜻하며, 액션을 빼고 방어만 허용
// _row : 행동과 방어를 빼고 정의
};
// pick a back-end
typedef msm::back::state_machine<player_> player;
static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
void pstate(player const& p)
{
std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
}
void MSM_TEST()
{
player p;
p.start();
p.process_event( open_close() ); pstate(p);
p.process_event( open_close() ); pstate(p);
p.process_event(cd_detected("louie, louie",DISK_DVD)); pstate(p);
p.process_event(cd_detected("louie, louie",DISK_CD)); pstate(p);
p.process_event(play()); pstate(p);
p.process_event(NextSong()); pstate(p);
p.process_event(NextSong()); pstate(p);
p.process_event(PreviousSong()); pstate(p);
p.process_event(pause()); pstate(p);
p.process_event(end_pause()); pstate(p);
p.process_event(pause()); pstate(p);
p.process_event(stop()); pstate(p);
p.process_event(stop()); pstate(p);
p.process_event(play()); pstate(p);
std::cout<< "stop fsm" << std::endl;
p.stop();
std::cout<< "restart fsm" << std::endl;
p.start();
getchar();
}
}
Boost MPL 샘플 (0) | 2016.01.29 |
---|---|
Boost Meta State Machine 테스트 2 (0) | 2016.01.29 |
Boost lock-free Queue 성능 테스트 (0) | 2016.01.29 |
Boost Fusion 샘플 (0) | 2016.01.29 |
Boost Function 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#pragma once
#include <Windows.h>
#include <boost/lockfree/queue.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/pool/object_pool.hpp>
#include <boost/lockfree/policies.hpp>
#include <boost/thread.hpp>
#include <boost/timer.hpp>
#include <boost/progress.hpp>
#pragma pack(push,4)
#define PACKET_TOTAL_SIZE 2048
#define PACKET_EOL_LENGTH 10
#define PACKET_MAX_BUFFER 2010
#define PACKET_HDR_SIZE 28//sizeof( UINT64 )
class CPacket
{
public:
union
{
// Restrict: ACK (Server to Client)
struct
{
UCHAR m_ucOwner;
UCHAR m_ucErr;
};
// Restrict: REQ (Client to Server)
USHORT m_usSerial; // Security: Record & Replay
};
USHORT m_usCmd; // internal command protocol
USHORT m_usPacketID; // packet id
USHORT m_usSize; // Stream data size (+PACKETHDR)
INT m_nHostID; // Host ID
DWORD64 m_dw64DBID; // DB ID
DWORD m_dwPacketOption; // packet option
DWORD m_dwDataCRC; // data crc
// EOL 사이즈를 포함한 크기
BYTE m_lpData [ 2020 ];
public:
CPacket()
{
setEmpty();
}
CPacket( const CPacket& _Right )
{
this->m_nHostID = _Right.m_nHostID;
//memcpy( this, _Right.segment(), _Right.size() );
memcpy( this->m_lpData, _Right.m_lpData, sizeof( BYTE ) * 2020 );
}
//// 튜플 대입 연산자 선언
//CPacket& operator=( const CPacket& _Right ) _THROW0()
//{
// memcpy( this->m_lpData, _Right.m_lpData, sizeof( BYTE ) * 2020 );
// return (*this);
//}
/*inline
VOID copy_of ( CPacket& _Right )
{ memcpy( this, _Right, _Right.size() ); }*/
/*~CPacket()
{
}*/
//BYTE* segment () const { return reinterpret_cast<BYTE*>(this); }
VOID CPacket::setEmpty()
{
ZeroMemory( this, PACKET_TOTAL_SIZE );
m_usSize = PACKET_TOTAL_SIZE;
}
// 스트림 총 크기
//USHORT& size () const { return m_usSize; }
};
#define CAPACITY_MAX 50000
//
// que 1
//
typedef boost::fast_pool_allocator< CPacket, boost::default_user_allocator_new_delete, boost::details::pool::null_mutex, 32, 0 > fast_pool_alloc_null_mutex;
fast_pool_alloc_null_mutex alloc1;
boost::lockfree::queue< CPacket, boost::lockfree::capacity<10000>, boost::lockfree::allocator< fast_pool_alloc_null_mutex > > que1( alloc1 );
//
// que 2
//
typedef boost::fast_pool_allocator< CPacket > fast_pool_alloc;
fast_pool_alloc alloc2;
boost::lockfree::queue< CPacket, boost::lockfree::capacity<10000>, boost::lockfree::allocator< fast_pool_alloc > > que2( alloc2 );
//
// que 3
//
boost::lockfree::spsc_queue< CPacket, boost::lockfree::capacity<10000> > que3;
//
// que 4
//
//boost::lockfree::queue< CPacket > que4;
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
void produce()
{
int i = 0;
for( ; i <= CAPACITY_MAX; ++i )
{
CPacket p;
p.m_nHostID = i;
//que1.bounded_push( p );
while( !que1.bounded_push( p ) );
}
}
void consume()
{
int i = 0;
for( ; i <= CAPACITY_MAX; )
{
CPacket p;
while( que1.pop(p))
{
++i;
sum1 += p.m_nHostID;
}
}
}
void produce2()
{
int i = 0;
for( ; i <= CAPACITY_MAX; ++i )
{
CPacket p;
p.m_nHostID = i;
while( !que2.bounded_push( p ) );
}
}
void consume2()
{
int i = 0;
for( ; i <= CAPACITY_MAX; )
{
CPacket p;
while( que2.pop(p))
{
++i;
sum2 += p.m_nHostID;
}
}
}
void produce3()
{
int i = 0;
for( ; i <= CAPACITY_MAX; ++i )
{
CPacket p;
p.m_nHostID = i;
while( !que3.push( p ) );
}
}
void consume3()
{
int i = 0;
for( ; i <= CAPACITY_MAX; )
{
CPacket p;
while( que3.pop(p))
{
++i;
sum3 += p.m_nHostID;
}
}
}
void lock_free_queue_test()
{
{
// 프로그레스 타이머
boost::progress_timer progress_t;
sum1 = 0;
boost::thread t1(produce);
boost::thread t2(consume);
t1.join();
t2.join();
//consume();
std::cout << "boost::lockfree::queue< CPacket, boost::lockfree::capacity<60000>, boost::lockfree::allocator< fast_pool_alloc_null_mutex > >" << std::endl;
std::cout << sum1 << "\n";
}
Sleep(10);
{
// 프로그레스 타이머
boost::progress_timer progress_t;
sum1 = 0;
boost::thread t1(produce2);
boost::thread t2(consume2);
t1.join();
t2.join();
//consume2();
std::cout << "boost::lockfree::queue< CPacket, boost::lockfree::capacity<60000>, boost::lockfree::allocator< fast_pool_alloc > >" << std::endl;
std::cout << sum2 << "\n";
}
Sleep(10);
{
// 프로그레스 타이머
boost::progress_timer progress_t;
sum1 = 0;
boost::thread t1(produce3);
boost::thread t2(consume3);
t1.join();
t2.join();
//consume3();
std::cout << "boost::lockfree::queue< CPacket, boost::lockfree::capacity<60000> >" << std::endl;
std::cout << sum3 << "\n";
}
//typedef boost::lockfree::spsc_queue< ENK::CPacket, boost::lockfree::capacity<65535>, boost::lockfree::allocator >
}
Boost Meta State Machine 테스트 2 (0) | 2016.01.29 |
---|---|
Boost Meta State Machine 테스트 (0) | 2016.01.29 |
Boost Fusion 샘플 (0) | 2016.01.29 |
Boost Function 샘플 (0) | 2016.01.29 |
Boost Format 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <boost/fusion/container.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/mpl/int.hpp>
#include <string>
#include <iostream>
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
void fusion_test()
{
typedef fusion::vector< int, std::string, bool ,double > vector_type;
vector_type v(10, "boost", true, 3.14 );
std::cout << fusion::at< mpl::int_<1>>(v) << std::endl;
}
Boost Meta State Machine 테스트 (0) | 2016.01.29 |
---|---|
Boost lock-free Queue 성능 테스트 (0) | 2016.01.29 |
Boost Function 샘플 (0) | 2016.01.29 |
Boost Format 샘플 (0) | 2016.01.29 |
Boost Foreach 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
#include <boost/function.hpp>
#include <vector>
#include <algorithm>
#include <boost/assign.hpp>
#include <boost/bind.hpp>
//
// 부스트 function 테스트
//
// assign도 같이 사용합니다.
//
// 같은 매개 변수를 같는 함수 2
int someFunction1( const char* )
{
return 1;
}
std::size_t someFunction2( const char* )
{
return 2;
}
//
// 일반 함수 일때 Function 테스트
void Function_With_Func_Test()
{
boost::function< int ( const char* ) > fp = someFunction1;
std::cout << fp("1234") << std::endl;
fp = someFunction2;
std::cout << fp("1234") << std::endl;
}
//
// 함수 객체 2
struct someFunctionObj1
{
int operator()( const char* ) const { return 1; }
};
struct someFunctionObj2
{
int operator()( const char* ) const { return 2; }
};
//
// 함수 객체 operator 일때 테스트
void Function_With_Operator_Test()
{
someFunctionObj1 func1;
someFunctionObj2 func2;
boost::function< int( const char* ) > fp = func1;
std::cout << fp("1234") << std::endl;
fp = func2;
std::cout << fp("1234") << std::endl;
fp = someFunction2;
std::cout << fp("1234") << std::endl;
// 기존 설정된 함수를 해제할떄는 0을 대입한다.
// 이후 function을 사용하면 boost::bad_function_call 발생
fp = 0;
try
{
std::cout << fp("1234") << std::endl;
}
catch (boost::bad_function_call& e)
{
std::cout << e.what() << std::endl;
}
}
struct world
{
int hello( const char* name )
{
std::cout<< "hello " << name << std::endl;
return 1;
}
};
//
// 멤버 함수를 설정하였을 경우 테스트
void Function_With_Member_Func_Test()
{
world w;
boost::function< int ( world*, const char* ) > fp = &world::hello;
fp( &w, "hong sung ki" );
}
//
//
struct Man
{
std::string name;
int say( const char* text )
{
std::cout<< "my name is " << name << std::endl;
std::cout<< "i need " << text << std::endl;
return 1;
}
};
struct Woman
{
std::string name;
int say( const char* text )
{
std::cout<< "my name is " << name << std::endl;
std::cout<< "i want " << text << std::endl;
return 2;
}
};
//
// function, bind 를 모두 배웠을 경우 컴비네이션으로 사용 가능한 방법
// 사실 이걸 사용하기위해 위의 예제들을 공부함
void Function_With_Bind_Test()
{
Man m1, m2;
m1.name = "skhong";
m2.name = "okidoki";
Woman w1, w2;
w1.name = "taehee";
// function 에 멤버 함수를 bind 해서 대입
boost::function< int ( const char* ) > fp = boost::bind( &Man::say, &m1, _1 );
std::cout<< fp("car") << std::endl;
// 같은 클래스의 다른 인스턴스를 대입 해도 가능
fp = boost::bind( &Man::say, &m2, _1 );
std::cout<< fp("girl") << std::endl;
// 다른 클래스의 멤버 함수지만 같은 시그니쳐를 가지고 있으므로
// bind를 통해서 한번 wrap 후 function에 대입 가능하다.
fp = boost::bind( &Woman::say, &w1, _1 );
std::cout<< fp("beuty") << std::endl;
}
Boost lock-free Queue 성능 테스트 (0) | 2016.01.29 |
---|---|
Boost Fusion 샘플 (0) | 2016.01.29 |
Boost Format 샘플 (0) | 2016.01.29 |
Boost Foreach 샘플 (0) | 2016.01.29 |
Boost Bind 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
#include <boost/format.hpp>
//
// iostream 형태의 파일 포맷을 극뽁!
// 형식, 인자의 개수에 관해서 안전
// 형식이 안전한 c++ 스타일의 printf와 비슷하다고 한다.
void Format_Test()
{
// 순서대로 표기
std::cout << boost::format("%1% %2%" ) % "hello" % 100 << std::endl;
// 역순으로 표기
std::cout << boost::format("%2% %1%" ) % "hello" % 100 << std::endl;
// %05d : 0포함 5자리수의 정수
// %x : 16진수 표기
// %f : float 형
// %% : % 표기
std::cout << boost::format("%05d %x %f %%") % 200 % 255 % 3.33f << std::endl;
// 변수에 받는것은 어떻게 하는것인지 찾아봐야 한다.
// %1% 과 %05d 는 섞어쓸수 없나보다.
// 에러가 남
// 정확하게 쓰려면 %1$05d 로 사용해야한다.
std::string txt = boost::io::str( boost::format("%1$05d %2$x %3$f") % 200 % 255 % 3.33f );
std::cout << " 변수 저장 : " << txt <<std::endl;
}
Boost Fusion 샘플 (0) | 2016.01.29 |
---|---|
Boost Function 샘플 (0) | 2016.01.29 |
Boost Foreach 샘플 (0) | 2016.01.29 |
Boost Bind 샘플 (0) | 2016.01.29 |
Boost Assign 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
#include <algorithm>
#include <wtypes.h>
#include <string>
#include <vector>
#include <map>
#include <stack>
// 벡터에 boost assign 을 사용한다.
// 더이상 자세한 설명은 생략한다.
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/foreach.hpp>
///
// boost_foreach 를 통해서 컨테이너 루프를 돌려보자.
// std::foreach 를 통해서 컨테이너 루프를 할경우 functor를 만들어야 하는데
// 귀찮음을 덜어줌
// assign 사용하기 위해서
using namespace boost::assign;
// Vector, boost_foreach 테스트
void Foreach_with_vector_test()
{
std::vector< int > v1;
v1.push_back( 100 );
v1.push_back( 200 );
v1.push_back( 300 );
v1.push_back( 400 );
v1.push_back( 500 );
BOOST_FOREACH( int& iter, v1 )
{
std::cout << "벡터 값 : " << iter << std::endl;
}
// boost assign 추가
std::vector< int > v2;// = { 100, 200, 300 };
// assign을 이용해서 대입
v2 += 1,2,3,4,5,6,7,8,9;
BOOST_FOREACH( int& iter, v2 )
{
std::cout << "벡터 값 : " << iter << std::endl;
}
}
void Foreach_with_map_test()
{
std::map< std::string, int > m1;
// 인서트
insert( m1 )
( "1월", 31 )( "2월", 28 )
( "3월", 31 )( "4월", 31 )
( "5월", 31 )( "6월", 31 )
( "7월", 31 )( "8월", 31 )
( "9월", 31 )( "10월", 31 )
( "11월", 31 )( "12월", 31 );
std::string key;
int value;
BOOST_FOREACH( boost::tie( key, value ), m1 )
{
std::cout << "Key : " << key << "Value : " << value << std::endl;
}
// 2번째 방법
typedef std::pair< std::string, int > pair_t;
BOOST_FOREACH( pair_t p, m1 )
{
std::cout << "Key : " << p.first << "Value : " << p.second << std::endl;
}
// 이건 안됨 에러임 매크로라서 , 를 인식해서 에러남
/*BOOST_FOREACH( std::pair< std::string, int > p, m1 )
{
std::cout << "Key : " << p.first << "Value : " << p.second << std::endl;
}*/
}
Boost Function 샘플 (0) | 2016.01.29 |
---|---|
Boost Format 샘플 (0) | 2016.01.29 |
Boost Bind 샘플 (0) | 2016.01.29 |
Boost Assign 샘플 (0) | 2016.01.29 |
Boost Array 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
#include <boost/function.hpp>
#include <vector>
#include <algorithm>
#include <boost/assign.hpp>
#include <boost/bind.hpp>
//
// boost::bind
//
// assign도 같이 사용합니다.
// 기존 bind1st, bind2st 등 stl 에서 지원해주던것을
// 좀더 간편하게 확장 버젼으로 사용 가능함
// 멤버 함수들도 손쉽게 바인드 가능
// 함수 매개변수 형식만 맞춰주면
// 어떤 클래스의 어떠한 멤버 함수들이라도 바인드 가능하다는
// 장점이 있어요!
using namespace boost::assign;
void print( int i )
{
std::cout<< i << std::endl;
}
void add( int i, int j )
{
std::cout<<i+j<<std::endl;
}
bool compare( int i , int j )
{
return i > j;
}
void Bind_Test()
{
// assign을 이용한 초기화
vector< int > v = list_of(1)(2)(3)(4).to_container( v );
std::for_each( v.begin(), v.end(), print );
// assign을 이용한 초기화2
vector< int > v2;
v2 += 1,2,3,4,5,6,7,8,9,10;
// foreach 를 통해서 이항 함수를 호출하고 싶을때
// 기존에는 functor를 생성하고
// std::binary_function<int,int,void> 형태로 만들어야 한다.
// 하지만 boost 를 이용하면 간단하게 아래와 같은 형식으로 사용 가능하다.
std::for_each( v2.begin(), v2.end(), boost::bind( add, 10, _1 ) );
}
void Bind_Test2()
{
std::vector< int > v;
v += 4,1,5,3,7,2,8;
// 내림 차순 정렬
std::cout << "내림차순 정렬" << std::endl;
std::sort( v.begin(), v.end(), boost::bind( compare, _1, _2 ) );
std::for_each( v.begin(), v.end(), print );
// 오름 차순 정렬
std::cout << "오름차순 정렬" << std::endl;
// 내림 차순 정렬에서 플레이스홀더 _1, _2 만 역으로 변경해주면
// 정렬 순서가 바뀌게 된다.
std::sort( v.begin(), v.end(), boost::bind( compare, _2, _1 ) );
std::for_each( v.begin(), v.end(), print );
}
// 멤버 함수 바인딩
class CMyTest
{
private:
std::vector< int > m_v;
public:
CMyTest()
{
m_v += 4,1,5,3,7,2,8;
}
void print( int i )
{
std::cout << i << std::endl;
}
bool compaire( int i, int j )
{
return i < j;
}
};
void Bind_Call_MemberFunc_Test()
{
CMyTest myTest;
boost::shared_ptr< CMyTest > spMyTest( new CMyTest() );
boost::bind( &CMyTest::print, boost::ref( myTest ), _1 )( 1 ); // myTest.print( 1 )
boost::bind( &CMyTest::print, &myTest, _1 )( 1 ); // (&myTest)->print( 1 )
boost::bind( &CMyTest::print, myTest, _1 )( 1 ); // (myTest의 복사본).print( 1 )
boost::bind( &CMyTest::print, spMyTest, _1 )( 1 ); // (spMyTest의 복사본)->print( 1 )
//std::sort( )
}
class CButton
{
private:
boost::function<void()> m_onClick;
public:
CButton( boost::function<void()> onClick )
{
m_onClick = onClick;
}
void doClick()
{
m_onClick();
}
};
class CPlayer
{
public:
void play()
{
std::cout<<"Do Play"<<std::endl;
}
void stop()
{
std::cout<<"Do Stop"<<std::endl;
}
};
// function 과 함께 bind를 사용하는 방법
// 같이 사용할 경우 멤버의 함수를 변수처럼 저장한 후 사용 가능하다.
void Bind_With_Function_Test()
{
CPlayer thePlayer;
CButton playBtn( boost::bind( &CPlayer::play, &thePlayer ) );
CButton stopBtn( boost::bind( &CPlayer::stop, &thePlayer ) );
playBtn.doClick();
stopBtn.doClick();
}
Boost Format 샘플 (0) | 2016.01.29 |
---|---|
Boost Foreach 샘플 (0) | 2016.01.29 |
Boost Assign 샘플 (0) | 2016.01.29 |
Boost Array 샘플 (0) | 2016.01.29 |
Boost Any 샘플 (0) | 2016.01.29 |
Boost 1.55 버전 기준으로 작성했습니다.
#include <iostream>
#include <algorithm>
#include <wtypes.h>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <boost/array.hpp>
// 벡터에 boost::assign 을 사용한다.
// 더이상 자세한 설명은 생략한다.
#include <boost/assign.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
using namespace boost::assign;
//
// stl container 초기화 또는 값을 대입하였을 경우
// 아주 아주 편리하게 도와주는 녀석
void Assign_Test()
{
vector< int > v = list_of(1)(2)(3)(4).to_container( v );
list< int > l = list_of(1)(2)(3)(4).to_container( l );
set< int > s = list_of(1)(2)(3)(4).to_container( s );
map< int,int > m = map_list_of(1,2)(2,3)(3,4)(4,5).to_container( m );
stack< int > st = list_of(1)(2)(3)(4).to_adapter( st );
queue< int > q = list_of(1)(2)(3)(4).to_adapter( q );
array< int, 4 > a = list_of(1)(2)(3)(4).to_array( a );
// v 출력
BOOST_FOREACH( int& iter, v )
{
std::cout << "벡터 값 : " << iter << std::endl;
}
// v 출력
BOOST_FOREACH( int& iter, l )
{
std::cout << "리스트 값 : " << iter << std::endl;
}
// v 출력
BOOST_FOREACH( int& iter, s )
{
std::cout << "Set 값 : " << iter << std::endl;
}
int key;
int value;
BOOST_FOREACH( boost::tie( key, value ), m )
{
std::cout << "Key : " << key << "Value : " << value << std::endl;
}
// v 출력
/*BOOST_FOREACH( int& iter, st )
{
std::cout << "Stack 값 : " << iter << std::endl;
}
// v 출력
BOOST_FOREACH( int& iter, q )
{
std::cout << "Queue 값 : " << iter << std::endl;
}*/
// v 출력
BOOST_FOREACH( int& iter, a )
{
std::cout << "Array 값 : " << iter << std::endl;
}
}
Boost Foreach 샘플 (0) | 2016.01.29 |
---|---|
Boost Bind 샘플 (0) | 2016.01.29 |
Boost Array 샘플 (0) | 2016.01.29 |
Boost Any 샘플 (0) | 2016.01.29 |
boost::mpl 라이브러리를 이용한 Packet의 자동 생성 및 처리 방법 (0) | 2014.05.26 |