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 |