C++ Template Metaprogramming
Solutions to the exercises throughout the book
Loading...
Searching...
No Matches
chapter-5-tiny.hpp
Go to the documentation of this file.
1// ===-- chapter-5/chapter-5-tiny.hpp --------------------- -*- C++ -*- --=== //
11
12
13#ifndef CHAPTER_5_TINY
14#define CHAPTER_5_TINY
15
16#include <boost/static_assert.hpp>
17
18#include <boost/mpl/at.hpp>
19#include <boost/mpl/begin_end.hpp>
20#include <boost/mpl/clear.hpp>
21#include <boost/mpl/insert.hpp>
22#include <boost/mpl/iterator_tags.hpp>
23#include <boost/mpl/minus.hpp>
24#include <boost/mpl/next_prior.hpp>
25#include <boost/mpl/plus.hpp>
26#include <boost/mpl/pop_back.hpp>
27#include <boost/mpl/pop_front.hpp>
28#include <boost/mpl/push_back.hpp>
29#include <boost/mpl/push_front.hpp>
30#include <boost/mpl/size.hpp>
31
32#include <boost/type_traits/is_same.hpp>
33
34
37namespace chapter5 {
38
40struct none { };
41
43struct tiny_tag {};
44
51template <typename Tiny, typename Pos>
53{
55 typedef boost::mpl::random_access_iterator_tag category;
56};
57
62template <typename T0 = none, typename T1 = none, typename T2 = none>
63struct tiny
64{
65 typedef tiny_tag tag;
66 typedef tiny type;
67 typedef T0 t0;
68 typedef T1 t1;
69 typedef T2 t2;
70};
71
73template <typename Tiny, int Pos> struct tiny_at { };
74
75template <typename Tiny>
76struct tiny_at<Tiny, 0>
77{
78 typedef typename Tiny::t0 type;
79};
80template <typename Tiny>
81struct tiny_at<Tiny, 1>
82{
83 typedef typename Tiny::t1 type;
84};
85template <typename Tiny>
86struct tiny_at<Tiny, 2>
87{
88 typedef typename Tiny::t2 type;
89};
90
91// Indirection to improve back insertion:
92
100template <typename Tiny, typename T, int N>
102
103template <typename Tiny, typename T>
104struct tiny_push_back<Tiny, T, 0> : tiny<T, none, none> { };
105template <typename Tiny, typename T>
106struct tiny_push_back<Tiny, T, 1> : tiny<typename Tiny::t0, T, none> { };
107template <typename Tiny, typename T>
108struct tiny_push_back<Tiny, T, 2>
109 : tiny<typename Tiny::t0, typename Tiny::t1, T> { };
110
111#ifndef PRE_EXERCISE_5_3
122template <typename Tiny, typename T, int N>
124
125template <typename Tiny, typename T>
126struct tiny_insert<Tiny, T, 0>
127 : tiny<T, typename Tiny::t0, typename Tiny::t1>
128{ BOOST_STATIC_ASSERT((boost::is_same<typename Tiny::t2, none>::value)); };
129template <typename Tiny, typename T>
130struct tiny_insert<Tiny, T, 1>
131 : tiny<typename Tiny::t0, T, typename Tiny::t1>
132{ BOOST_STATIC_ASSERT((boost::is_same<typename Tiny::t2, none>::value)); };
133template <typename Tiny, typename T>
134struct tiny_insert<Tiny, T, 2>
135 : tiny<typename Tiny::t0, typename Tiny::t1, T>
136{ BOOST_STATIC_ASSERT((boost::is_same<typename Tiny::t2, none>::value)); };
137#endif
138
140template <typename T0, typename T1, typename T2>
141struct tiny_size : boost::mpl::int_<3> { };
142
143template <typename T0, typename T1>
144struct tiny_size<T0, T1, none> : boost::mpl::int_<2> { };
145template <typename T0>
146struct tiny_size<T0, none, none> : boost::mpl::int_<1> { };
147template <>
148struct tiny_size<none, none, none> : boost::mpl::int_<0> { };
149
150} // namespace chapter5
151
152
153namespace boost {
154namespace mpl {
155
158
159// Implement the required operations
160
162template <typename Tiny, typename Pos>
163struct next< chapter5::tiny_iterator<Tiny,Pos> >
164{
166 Tiny,
167 typename boost::mpl::next<Pos>::type
169};
170
172template <typename Tiny, typename Pos>
173struct prior< chapter5::tiny_iterator<Tiny,Pos> >
174{
176 Tiny,
177 typename boost::mpl::prior<Pos>::type
179};
180
182template <typename Tiny, typename Pos, typename N>
183struct advance< chapter5::tiny_iterator<Tiny,Pos>, N >
184{
186 Tiny,
187 typename boost::mpl::plus<Pos,N>::type
189};
190
193template <typename Tiny, typename Pos>
194struct deref< chapter5::tiny_iterator<Tiny,Pos> > : at<Tiny,Pos> { };
195
197template <typename Tiny, typename Pos1, typename Pos2>
198struct distance<
199 chapter5::tiny_iterator<Tiny,Pos1>,
200 chapter5::tiny_iterator<Tiny,Pos2> >
201 : boost::mpl::minus<Pos2, Pos1> { };
202
204template <>
205struct at_impl<chapter5::tiny_tag>
206{
207 template <typename Tiny, typename N>
208 struct apply : chapter5::tiny_at<Tiny, N::value> { };
209};
210
212template <>
213struct begin_impl<chapter5::tiny_tag>
214{
215 template <typename Tiny>
216 struct apply
217 {
219 };
220};
221
223template <>
224struct end_impl<chapter5::tiny_tag>
225{
226 template <typename Tiny>
227 struct apply
228 {
230 Tiny,
231 typename chapter5::tiny_size<
232 typename Tiny::t0,
233 typename Tiny::t1,
234 typename Tiny::t2
235 >::type
237 };
238};
239
241template <>
242struct size_impl<chapter5::tiny_tag>
243{
244 template <typename Tiny>
245 struct apply
247 typename Tiny::t0,
248 typename Tiny::t1,
249 typename Tiny::t2
250 > { };
251};
252
253// Extensibility
254
256template <>
257struct clear_impl<chapter5::tiny_tag>
258{
259 template <typename Tiny>
260 struct apply : chapter5::tiny<> { };
261};
262
264template <>
265struct push_back_impl<chapter5::tiny_tag>
266{
267 // tiny_push_back and tiny_insert are the same complexity.
268 template <typename Tiny, typename T>
269#ifdef PRE_EXERCISE_5_3
270 struct apply
271 : tiny_push_back<Tiny, T, size<Tiny>::value> { };
272#else
273 struct apply
274 : chapter5::tiny_insert<Tiny, T, size<Tiny>::value> { };
275#endif
276};
277
279
290// (Changed) A simple assert that either t2 = none, or size<Tiny> < 3
291
294template <>
295struct push_front_impl<chapter5::tiny_tag>
296{
297 template <typename Tiny, typename T>
298 struct apply : chapter5::tiny<T, typename Tiny::t0, typename Tiny::t1>
299 {
300 // See exercise 5-2
302 boost::is_same<typename Tiny::t2, chapter5::none>::value));
303 };
304};
305
318// Created tiny_insert, modified push_back (above)
319
322template <>
323struct insert_impl<chapter5::tiny_tag>
324{
325 template <typename Tiny, typename Pos, typename T>
326 struct apply;
327
328 template <typename Tiny, typename Pos, typename T>
329 struct apply<Tiny, chapter5::tiny_iterator<Tiny,Pos>, T>
330 : chapter5::tiny_insert<Tiny, T, Pos::value> { };
331};
332
333} // namespace mpl
334} // namespace boost
335
336
360#include <boost/mpl/erase.hpp>
361
362namespace chapter5 {
363
366
374template <typename S, int First, int Last>
375struct tiny_erase { };
376
377template <typename S>
378struct tiny_erase<S,0,1> : tiny<typename S::t1, typename S::t2> { };
379template <typename S>
380struct tiny_erase<S,0,2> : tiny<typename S::t2> { };
381template <typename S>
382struct tiny_erase<S,0,3> : tiny<> { };
383template <typename S>
384struct tiny_erase<S,1,2> : tiny<typename S::t0, typename S::t2> { };
385template <typename S>
386struct tiny_erase<S,1,3> : tiny<typename S::t0> { };
387template <typename S>
388struct tiny_erase<S,2,3> : tiny<typename S::t0, typename S::t1> { };
389
391
392} // namespace chapter5
393
394
395namespace boost {
396namespace mpl {
397
400
402template<>
403struct erase_impl<chapter5::tiny_tag>
404{
405 template <typename S, typename First, typename Last>
406 struct apply { };
407
408 // We have no end, so ask to delete [First, First+1)...
409 template <typename S, typename First>
410 struct apply<S, First, mpl_::na /* ??? */>
411 : apply<S, First, typename boost::mpl::next<First>::type> { };
412
413 template <typename S, typename First, typename Last>
414 struct apply< S,
415 chapter5::tiny_iterator<S, First>,
416 chapter5::tiny_iterator<S, Last> >
417 : chapter5::tiny_erase<S, First::value, Last::value> { };
418};
419
421template<>
422struct pop_back_impl<chapter5::tiny_tag>
423{
424 template <typename S>
425 struct apply
426 : erase_impl<chapter5::tiny_tag>::template apply<
427 S,
428 typename prior<typename end<S>::type>::type,
429 typename end<S>::type> { };
430};
431
433template<>
434struct pop_front_impl<chapter5::tiny_tag>
435{
436 template <typename S>
437 struct apply
438 : erase_impl<chapter5::tiny_tag>::template apply<
439 S,
440 typename begin<S>::type,
441 typename next<typename begin<S>::type>::type> { };
442};
443
445
446} // namespace mpl
447} // namespace boost
448
449#endif // CHAPTER_5_TINY
Exists to inject functionality into the Boost MPL namespace.
Exists to inject functionality into the Boost namespace.
Provide utilities availble to all Chapter 5 solutions.
chapter5::tiny_iterator< Tiny, typename boost::mpl::plus< Pos, N >::type > type
chapter5::tiny_iterator< Tiny, int_< 0 > > type
chapter5::tiny_iterator< Tiny, typename chapter5::tiny_size< typename Tiny::t0, typename Tiny::t1, typename Tiny::t2 >::type > type
chapter5::tiny_iterator< Tiny, typename boost::mpl::next< Pos >::type > type
chapter5::tiny_iterator< Tiny, typename boost::mpl::prior< Pos >::type > type
BOOST_STATIC_ASSERT((boost::is_same< typename Tiny::t2, chapter5::none >::value))
Quickly define a NULL type.
Provide O(1) access to sequences tagged with tiny_tag.
Erase a range of elements from a tiny sequence.
BOOST_STATIC_ASSERT((boost::is_same< typename Tiny::t2, none >::value))
BOOST_STATIC_ASSERT((boost::is_same< typename Tiny::t2, none >::value))
BOOST_STATIC_ASSERT((boost::is_same< typename Tiny::t2, none >::value))
Insert into the tiny sequence.
Define an iterator for use with the tiny sequence type.
boost::mpl::random_access_iterator_tag category
The tiny sequence has Random Access iteration semantics.
Add an element to the end of the tiny sequence.
Used to improve end metafunction performance, etc.
Type for tag-based implementation of algorithms below.
A small, random-access sequence type.