// (by Ariel Badichi) #include <boost/static_assert.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/mpl/iterator_tags.hpp> #include <boost/mpl/next.hpp> #include <boost/mpl/prior.hpp> #include <boost/mpl/at.hpp> #include <boost/mpl/deref.hpp> #include <boost/mpl/advance.hpp> #include <boost/mpl/distance.hpp> #include <boost/mpl/plus.hpp> #include <boost/mpl/minus.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/size.hpp> #include <boost/mpl/clear.hpp> #include <boost/mpl/push_front.hpp> #include <boost/mpl/push_back.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/greater.hpp> #include <boost/mpl/less.hpp> #include <boost/mpl/void.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/equal.hpp> #include <boost/mpl/insert.hpp> #include <boost/mpl/pop_front.hpp> #include <boost/mpl/pop_back.hpp> #include <boost/mpl/erase.hpp>
namespace mpl = boost::mpl;
typedef mpl::int_<0> zero; typedef mpl::int_<1> one; typedef mpl::int_<2> two; typedef mpl::int_<3> three;
struct none {}; struct tiny_tag {};
template<typename T0 = none, typename T1 = none, typename T2 = none> struct tiny { typedef tiny_tag tag; typedef tiny type; typedef T0 t0; typedef T1 t1; typedef T2 t2; };
template<typename Tiny, typename Pos> struct tiny_iterator { typedef mpl::random_access_iterator_tag category; };
template<typename Tiny, int N> struct tiny_at;
template<typename Tiny> struct tiny_at<Tiny, 0> { typedef typename Tiny::t0 type; };
template<typename Tiny> struct tiny_at<Tiny, 1> { typedef typename Tiny::t1 type; };
template<typename Tiny> struct tiny_at<Tiny, 2> { typedef typename Tiny::t2 type; };
template<typename T0, typename T1, typename T2> struct tiny_size : three {};
template<typename T0, typename T1> struct tiny_size<T0, T1, none> : two {};
template<typename T0> struct tiny_size<T0, none, none> : one {};
template<> struct tiny_size<none, none, none> : zero {};
/* template<typename Tiny, typename T, int N> struct tiny_push_back;
template<typename Tiny, typename T> struct tiny_push_back<Tiny, T, 0> : tiny<T> {};
template<typename Tiny, typename T> struct tiny_push_back<Tiny, T, 1> : tiny<typename Tiny::t0, T> {};
template<typename Tiny, typename T> struct tiny_push_back<Tiny, T, 2> : tiny<typename Tiny::t0, typename Tiny::t1, T> {}; */
template<typename Tiny> struct check_not_full { BOOST_STATIC_ASSERT((mpl::less< typename mpl::size<Tiny>::type, three >::value)); };
template<typename Tiny> struct check_not_empty { BOOST_STATIC_ASSERT((mpl::greater< typename mpl::size<Tiny>::type, zero >::value)); };
template<typename Tiny, typename T, int N> struct tiny_insert;
template<typename Tiny, typename T> struct tiny_insert<Tiny, T, 0> : tiny<T, typename Tiny::t0, typename Tiny::t1> , check_not_full<Tiny> {};
template<typename Tiny, typename T> struct tiny_insert<Tiny, T, 1> : tiny<typename Tiny::t0, T, typename Tiny::t1> , check_not_full<Tiny> {};
template<typename Tiny, typename T> struct tiny_insert<Tiny, T, 2> : tiny<typename Tiny::t0, typename Tiny::t1, T> , check_not_full<Tiny> {};
template<typename T0, typename T1, typename T2> struct tiny_pop_front : tiny<T1, T2> {};
template<typename T0, typename T1, typename T2> struct tiny_pop_back : tiny<T0, T1> {};
template<typename T0, typename T1> struct tiny_pop_back<T0, T1, none> : tiny<T0> {};
template<typename T0> struct tiny_pop_back<T0, none, none> : tiny<> {};
template<typename Tiny, int N> struct tiny_erase;
template<typename Tiny> struct tiny_erase<Tiny, 0> : tiny<typename Tiny::t1, typename Tiny::t2> {};
template<typename Tiny> struct tiny_erase<Tiny, 1> : tiny<typename Tiny::t0, typename Tiny::t2> {};
template<typename Tiny> struct tiny_erase<Tiny, 2> : tiny<typename Tiny::t0, typename Tiny::t1> {};
template<typename Tiny, typename Pos> struct tiny_has_item : mpl::eval_if< mpl::and_< mpl::greater< typename mpl::size<Tiny>::type, Pos >, mpl::greater< Pos, mpl::prior<zero>::type > >,
mpl::true_, mpl::false_ > {};
template<typename Tiny, int First, int Last> struct tiny_erase_range;
template<typename Tiny> struct tiny_erase_range<Tiny, 0, 1> : mpl::erase<Tiny, tiny_iterator<Tiny, zero> > {};
template<typename Tiny> struct tiny_erase_range<Tiny, 0, 2> { typedef typename mpl::erase<Tiny, tiny_iterator<Tiny, one> >::type temp; typedef typename mpl::erase<temp, tiny_iterator<temp, zero> >::type type; };
template<typename Tiny> struct tiny_erase_range<Tiny, 0, 3> { typedef typename mpl::erase<Tiny, tiny_iterator<Tiny, two> >::type tmp1; typedef typename mpl::erase<tmp1, tiny_iterator<tmp1, one> >::type tmp2; typedef typename mpl::erase<tmp2, tiny_iterator<tmp2, zero> >::type type; };
template<typename Tiny> struct tiny_erase_range<Tiny, 1, 2> : mpl::erase<Tiny, tiny_iterator<Tiny, one> > {};
template<typename Tiny> struct tiny_erase_range<Tiny, 1, 3> { typedef typename mpl::erase<Tiny, tiny_iterator<Tiny, two> >::type tmp1; typedef typename mpl::erase<tmp1, tiny_iterator<tmp1, one> >::type type; };
template<typename Tiny> struct tiny_erase_range<Tiny, 2, 3> : mpl::erase<Tiny, tiny_iterator<Tiny, two> > {};
namespace boost { namespace mpl { template<typename Tiny, typename Pos> struct next<tiny_iterator<Tiny, Pos> > { BOOST_STATIC_ASSERT((mpl::greater< typename size<Tiny>::type, Pos >::value));
typedef tiny_iterator<Tiny, typename mpl::next<Pos>::type> type; };
template<typename Tiny, typename Pos> struct prior<tiny_iterator<Tiny, Pos> > { BOOST_STATIC_ASSERT((mpl::greater< Pos, zero >::value));
typedef tiny_iterator<Tiny, typename mpl::prior<Pos>::type> type; };
template<> struct at_impl<tiny_tag> { template<typename Tiny, typename N> struct apply : tiny_at<Tiny, N::value> { BOOST_STATIC_ASSERT((mpl::greater< typename size<Tiny>::type, N >::value)); }; };
template<typename Tiny, typename Pos> struct deref<tiny_iterator<Tiny, Pos> > : at<Tiny, Pos> {};
template<typename Tiny, typename Pos, typename N> struct advance<tiny_iterator<Tiny, Pos>, N> { typedef typename mpl::plus<Pos, N>::type new_pos;
BOOST_STATIC_ASSERT((mpl::greater< typename size<Tiny>::type, new_pos >::value));
BOOST_STATIC_ASSERT((mpl::greater< new_pos, mpl::int_<-1> >::value));
typedef tiny_iterator< Tiny, new_pos > type; };
template<typename Tiny, typename Pos1, typename Pos2> struct distance<tiny_iterator<Tiny, Pos1>, tiny_iterator<Tiny, Pos2> > : mpl::minus<Pos2, Pos1> {};
template<> struct begin_impl<tiny_tag> { template<typename Tiny> struct apply { typedef tiny_iterator<Tiny, zero> type; }; };
template<> struct end_impl<tiny_tag> { template<typename Tiny> struct apply { typedef tiny_iterator< Tiny, typename tiny_size< typename Tiny::t0, typename Tiny::t1, typename Tiny::t2 >::type > type; }; };
template<> struct size_impl<tiny_tag> { template<typename Tiny> struct apply : tiny_size< typename Tiny::t0, typename Tiny::t1, typename Tiny::t2 > {}; };
template<> struct clear_impl<tiny_tag> { template<typename Tiny> struct apply : tiny<> {}; };
template<> struct push_front_impl<tiny_tag> { template<typename Tiny, typename T> struct apply : tiny<T, typename Tiny::t0, typename Tiny::t1> { BOOST_STATIC_ASSERT((mpl::less< typename size<Tiny>::type, three >::value)); }; };
template<> struct push_back_impl<tiny_tag> { template<typename Tiny, typename T> struct apply : tiny_insert<Tiny, T, size<Tiny>::value> {}; };
template<> struct insert_impl<tiny_tag> { template<typename Tiny, typename Pos, typename T> struct apply;
template<typename Tiny, typename Pos, typename T> struct apply<Tiny, tiny_iterator<Tiny, Pos>, T> : tiny_insert<Tiny, T, Pos::value> {}; };
template<> struct pop_front_impl<tiny_tag> { template<typename Tiny> struct apply : check_not_empty<Tiny> , tiny_pop_front< typename Tiny::t0, typename Tiny::t1, typename Tiny::t2 > {}; };
template<> struct pop_back_impl<tiny_tag> { template<typename Tiny> struct apply : check_not_empty<Tiny> , tiny_pop_back< typename Tiny::t0, typename Tiny::t1, typename Tiny::t2 > {}; };
template<> struct erase_impl<tiny_tag> { template<typename Tiny, typename First, typename Last> struct apply;
template<typename Tiny, typename First, typename Last> struct apply<Tiny, tiny_iterator<Tiny, First>, Last> : tiny_erase<Tiny, First::value> { BOOST_STATIC_ASSERT((tiny_has_item< Tiny, First >::type::value)); };
template<typename Tiny, typename First, typename Last> struct apply< Tiny, tiny_iterator<Tiny, First>, tiny_iterator<Tiny, Last> > : tiny_erase_range<Tiny, First::value, Last::value> { }; }; } }
template<typename Tiny, typename Pos> struct check_at { typedef typename mpl::at<Tiny, Pos>::type item_at;
typedef typename mpl::begin<Tiny>::type beg; typedef typename mpl::deref< typename mpl::advance<beg, Pos>::type >::type item;
BOOST_STATIC_ASSERT((boost::is_same<item_at, item>::value));
typedef check_at type; };
template<typename Tiny> struct test { typedef test type;
BOOST_STATIC_ASSERT((boost::is_same<Tiny, typename Tiny::type>::value));
typedef typename mpl::begin<Tiny>::type beg; typedef typename mpl::end<Tiny>::type end; typedef typename mpl::distance<beg, end>::type distance; typedef typename mpl::size<Tiny>::type size;
BOOST_STATIC_ASSERT(size::value == distance::value);
typedef typename mpl::eval_if< mpl::greater<size, two>, check_at<Tiny, two>, mpl::true_ >::type at2;
typedef typename mpl::eval_if< mpl::greater<size, one>, check_at<Tiny, one>, mpl::true_ >::type at1;
typedef typename mpl::eval_if< mpl::greater<size, zero>, check_at<Tiny, zero>, mpl::true_ >::type at0; };
int main() { typedef tiny<> tiny0; typedef tiny<int> tiny1; typedef tiny<char *, const long> tiny2; typedef tiny<unsigned short, double &, bool> tiny3;
test<tiny0>::type; test<tiny1>::type; test<tiny2>::type; test<tiny3>::type;
typedef mpl::clear<tiny3>::type clean; BOOST_STATIC_ASSERT((mpl::equal<tiny0, clean>::type::value));
{ typedef mpl::push_front<tiny0, int>::type tiny0_1; typedef mpl::push_front<tiny1, int>::type tiny1_2; typedef mpl::push_front<tiny2, int>::type tiny2_3; //typedef mpl::push_front<tiny3, int>::type invalid; }
{ typedef mpl::push_back<tiny0, int>::type tiny0_1; typedef mpl::push_back<tiny1, int>::type tiny1_2; typedef mpl::push_back<tiny2, int>::type tiny2_3; //typedef mpl::push_back<tiny3, int>::type invalid; }
{ //typedef mpl::at<tiny0, zero>::type invalid; }
{ typedef mpl::begin<tiny0>::type beg; //typedef mpl::next<beg>::type invalid; }
{ typedef mpl::begin<tiny0>::type beg; //typedef mpl::deref<beg>::type invalid; }
{ typedef mpl::end<tiny0>::type end; //typedef mpl::prior<end>::type invalid; }
{ typedef mpl::begin<tiny0>::type beg; //typedef mpl::advance<beg, one>::type invalid; }
{ typedef mpl::end<tiny0>::type end; //typedef mpl::advance<end, mpl::int_<-1> >::type invalid; }
{ typedef tiny_iterator<tiny0, zero> i0; typedef mpl::insert<tiny0, i0, long>::type i0_1; BOOST_STATIC_ASSERT((mpl::equal<i0_1, tiny<long> >::type::value)); typedef tiny_iterator<i0_1, zero> i1; typedef mpl::insert<i0_1, i1, int>::type i1_2; BOOST_STATIC_ASSERT((mpl::equal< i1_2, tiny<int, long> >::type::value)); typedef tiny_iterator<i1_2, zero> i2; typedef mpl::insert<i1_2, i2, char>::type i2_3; BOOST_STATIC_ASSERT((mpl::equal< i2_3, tiny<char, int, long> >::type::value)); typedef tiny_iterator<i2_3, zero> i3; //typedef mpl::insert<i2_3, i3, bool>::type invalid; }
{ typedef tiny_iterator<tiny1, one> i0; typedef mpl::insert<tiny1, i0, long>::type i1_2; BOOST_STATIC_ASSERT((mpl::equal< i1_2, tiny<int, long> >::type::value)); typedef tiny_iterator<i1_2, one> i1; typedef mpl::insert<i1_2, i1, char>::type i2_3; BOOST_STATIC_ASSERT((mpl::equal< i2_3, tiny<int, char, long> >::type::value)); typedef tiny_iterator<i2_3, one> i2; //typedef mpl::insert<i2_3, i2, bool>::type invalid; }
{ typedef tiny_iterator<tiny2, two> i0; typedef mpl::insert<tiny2, i0, long>::type i2_3; BOOST_STATIC_ASSERT((mpl::equal< i2_3, tiny<char *, const long, long> >::type::value)); typedef tiny_iterator<i2_3, two> i1; //typedef mpl::insert<i2_3, i1, char>::type invalid; }
{ typedef mpl::pop_front<tiny3>::type t2; BOOST_STATIC_ASSERT((mpl::equal< t2, tiny<double &, bool> >::type::value)); typedef mpl::pop_front<t2>::type t1; BOOST_STATIC_ASSERT((mpl::equal< t1, tiny<bool> >::type::value)); typedef mpl::pop_front<t1>::type t0; BOOST_STATIC_ASSERT((mpl::equal<t0, tiny<> >::type::value)); //typedef mpl::pop_front<t0>::type invalid; }
{ typedef mpl::pop_back<tiny3>::type t2; BOOST_STATIC_ASSERT((mpl::equal< t2, tiny<unsigned short, double &> >::type::value)); typedef mpl::pop_back<t2>::type t1; BOOST_STATIC_ASSERT((mpl::equal< t1, tiny<unsigned short> >::type::value)); typedef mpl::pop_back<t1>::type t0; BOOST_STATIC_ASSERT((mpl::equal<t0, tiny<> >::type::value)); //typedef mpl::pop_back<t0>::type invalid; }
{ typedef tiny_iterator<tiny3, zero> i0; typedef mpl::erase<tiny3, i0>::type e0; BOOST_STATIC_ASSERT((mpl::equal< e0, tiny<double &, bool> >::type::value));
typedef tiny_iterator<tiny3, one> i1; typedef mpl::erase<tiny3, i1>::type e1; BOOST_STATIC_ASSERT((mpl::equal< e1, tiny<unsigned short, bool> >::type::value));
typedef tiny_iterator<tiny3, two> i2; typedef mpl::erase<tiny3, i2>::type e2; BOOST_STATIC_ASSERT((mpl::equal< e2, tiny<unsigned short, double &> >::type::value)); }
{ typedef tiny_iterator<tiny2, zero> i0; typedef mpl::erase<tiny2, i0>::type e0; BOOST_STATIC_ASSERT((mpl::equal<e0, tiny<const long> >::type::value));
typedef tiny_iterator<tiny2, one> i1; typedef mpl::erase<tiny2, i1>::type e1; BOOST_STATIC_ASSERT((mpl::equal<e1, tiny<char *> >::type::value));
typedef tiny_iterator<tiny2, two> i2; //typedef mpl::erase<tiny2, i2>::type invalid; }
{ typedef tiny_iterator<tiny1, zero> i0; typedef mpl::erase<tiny1, i0>::type e0; BOOST_STATIC_ASSERT((mpl::equal<e0, tiny<> >::type::value));
typedef tiny_iterator<tiny1, one> i1; //typedef mpl::erase<tiny1, i1>::type invalid; }
{ typedef tiny_iterator<tiny0, zero> i0; //typedef mpl::erase<tiny0, i0>::type invalid; }
{ typedef tiny_iterator<tiny3, zero> i0; typedef tiny_iterator<tiny3, one> i1; typedef tiny_iterator<tiny3, two> i2; typedef tiny_iterator<tiny3, three> i3;
//typedef mpl::erase<tiny3, i0, i0>::type invalid0;
typedef mpl::erase<tiny3, i0, i1>::type e0; BOOST_STATIC_ASSERT((mpl::equal<e0, tiny<double &, bool> >::type::value));
typedef mpl::erase<tiny3, i0, i2>::type e1; BOOST_STATIC_ASSERT((mpl::equal<e1, tiny<bool> >::type::value));
typedef mpl::erase<tiny3, i0, i3>::type e2; BOOST_STATIC_ASSERT((mpl::equal<e2, tiny<> >::type::value));
//typedef mpl::erase<tiny3, i1, i1>::type invalid1;
typedef mpl::erase<tiny3, i1, i2>::type e3; BOOST_STATIC_ASSERT((mpl::equal<e3, tiny<unsigned short, bool> >::type::value));
typedef mpl::erase<tiny3, i1, i3>::type e4; BOOST_STATIC_ASSERT((mpl::equal<e4, tiny<unsigned short> >::type::value));
//typedef mpl::erase<tiny3, i2, i2>::type invalid2;
typedef mpl::erase<tiny3, i2, i3>::type e5; BOOST_STATIC_ASSERT((mpl::equal<e5, tiny<unsigned short, double &> >::type::value)); }
{ typedef tiny_iterator<tiny2, zero> i0; typedef tiny_iterator<tiny2, one> i1; typedef tiny_iterator<tiny2, two> i2; typedef tiny_iterator<tiny2, three> i3;
typedef mpl::erase<tiny2, i0, i1>::type e0; BOOST_STATIC_ASSERT((mpl::equal<e0, tiny<const long> >::type::value));
typedef mpl::erase<tiny2, i0, i2>::type e1; BOOST_STATIC_ASSERT((mpl::equal<e1, tiny<> >::type::value));
//typedef mpl::erase<tiny2, i0, i3>::type invalid0;
typedef mpl::erase<tiny2, i1, i2>::type e2; BOOST_STATIC_ASSERT((mpl::equal<e2, tiny<char *> >::type::value));
//typedef mpl::erase<tiny2, i1, i3>::type invalid1; //typedef mpl::erase<tiny2, i2, i3>::type invalid2; }
{ typedef tiny_iterator<tiny1, zero> i0; typedef tiny_iterator<tiny1, one> i1; typedef tiny_iterator<tiny1, two> i2;
typedef mpl::erase<tiny1, i0, i1>::type e0; BOOST_STATIC_ASSERT((mpl::equal<e0, tiny<> >::type::value));
//typedef mpl::erase<tiny1, i0, i2>::type invalid0; //typedef mpl::erase<tiny1, i1, i2>::type invalid1; }
{ typedef tiny_iterator<tiny0, zero> i0; typedef tiny_iterator<tiny0, one> i1;
//typedef mpl::erase<tiny0, i0, i1>::type invalid; }
return 0; }