Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Preprocessor Programming

720 views

Published on

c++ preprocessor programming for explanation of boost pp

Published in: Engineering, Technology, Business
  • Be the first to comment

Preprocessor Programming

  1. 1. Preprocessor programming 2013. 08. 23. 최재영
  2. 2. Motivation • Don’t Repeat Yourself! 2 template <class T> DoAsync(void (T::*member)()) {} template <class T, class A1> DoAsync(void (T::*member)(), A1 a1) {} template <class T, class A1, class A2> DoAsync(void (T::*member)(), A1 a1, A2 a2) {} template <class T, class A1, class A2, class A3> DoAsync(void (T::*member)(), A1 a1, A2 a2, A3 a3) {} template <class T, class A1, class A2, class A3, class A4> DoAsync(void (T::*member)(), A1 a1, A2 a2, A3 a3, A4 a4) {} enum SomeType { TypeA, TypeB, }; const TCHAR* GetSomeTypeName(SomeType type) { if (type == TypeA) return _T("TypeA"); if (type == TypeB) return _T("TypeB"); return _T(""); }
  3. 3. Why? • generate code that cannot be generated by template • or generate boilerplate template code 3 concat token repetition multi-pass generation a ## b #include "repl_a.h" #include "spec.h" #include "repl_b.h" #include "spec.h" #define TARGET "spec.h" #include "iteration.h" #define DECL(name) template <REPEAT(MAX_SIZE, class T)>
  4. 4. 흐름 4 X-Macro repetition Boost PP horizontal vertical
  5. 5. Fundamentals 5 // object-like macro #define <identifier> <replacement token list> // function-like macro, note parameters #define <identifier>(<parameter list>) <replacement token list> // local macro #define <identifier> /* do something */ #undef <identifier> • Macro expansion in the preprocessor is entirely functional. But the preprocessor disallows recursion.
  6. 6. Fundamentals (cont.) 6 // reentrancy problem #define CONCAT(a, b) a ## b #define AB(x, y) CONCAT(x, y) CONCAT(A, B(p, q)) // CONCAT(p, q), not pq // solving the one-depth reentrancy problem #define CONCAT2(a, b) a ## b #define AB(x, y) CONCAT(x, y) #define CONCAT(a, b) CONCAT2(a, b) CONCAT(A, B(p, q)) // pq • How many recursion-depth does it support? • How many case does it define?
  7. 7. X-Macro • generating repeating code structures at compile time 7 enum SomeType { ST_SOME, ST_OTHER }; inline const TCHAR* GetNameFromSomeType(SomeType type) { if (type == ST_SOME) return _T("ST_SOME"); if (type == ST_OTHER) return _T("ST_OTHER"); return _T(""); } inline SomeType GetSomeTypeFromName(const TCHAR* str) { if (_tcsicmp(str, _T("ST_SOME") == 0) return ST_SOME; if (_tcsicmp(str, _T("ST_OTHER") == 0) return ST_OTHER; return static_cast<SomeType>(-1); }
  8. 8. X-Macro (cont.) 8 ENUM_BEGIN(SomeType) ENUM(ST_SOME) ENUM(ST_OTHER) ENUM_END(SomeType) #define ENUM_BEGIN(name) enum name { #define ENUM(name) name, #define ENUM_END(name) }; #define ENUM_BEGIN(name) inline const TCHAR* GetNameFrom##name##(name type) { #define ENUM(name) if (type == name) return _T(#name); #define ENUM_END(name) return _T(""); } #define ENUM_BEGIN(name) inline name Get##name##FromName(const TCHAR* str) { #define ENUM(name) if (_tcsicmp(str, #name) == 0) return name; #define ENUM_END(name) return static_cast<name>(-1); } sometype_spec.h enum_decl_gen.h enum_to_str_gen.h str_to_enum_gen.h
  9. 9. X-Macro (cont.) 9 #include "enum_decl_gen.h" #include "sometype_spec.h" enums.h #include "enum_to_str_gen.h" #include "sometype_spec.h" #include "enum_gen_reset.h" #include "str_to_enum_gen.h" #include "sometype_spec.h" enums.cpp #undef ENUM_BEGIN #undef ENUM #undef ENUM_END enum_gen_reset.h
  10. 10. Repetition • horizontal repetition • vertical repetition 10 template <class T> void DoAsync(...); template <class T, class A0> void DoAsync(...); template <class T, class A0, class A1> void DoAsync(...); template <class T, class A0, class A1, class A2> void DoAsync(...); template <class T, class A0, class A1, class A2, class A3> void DoAsync(...); vertical horizontal
  11. 11. Horizontal Repetition (cont.) • the preprocessor disallows recursion. • all cases should be defined. 11 #define REPEAT_1(m) m(0) #define REPEAT_2(m) REPEAT_1(m), m(1) #define REPEAT_3(m) REPEAT_2(m), m(2) #define REPEAT_4(m) REPEAT_3(m), m(3) #define REPEAT_5(m) REPEAT_4(m), m(4) // ... #define REPEAT(c, m) CONCAT(REPEAT_, c)(m) chaining end condition case selector
  12. 12. Horizontal Repetition (cont.) 12 generator#define REPEAT_PARAM(n) class T ## n template <class R, REPEAT(4, REPEAT_PARAM)> struct test_t {}; repeat count template <class R, class T0, class T1, class T2, class T3> struct test_t {}; repeated expand!
  13. 13. Vertical Repetition (cont.) • macro state & self-include 13 #if !defined(CURRENT) # define CURRENT 0 # include "repeater.h" #elif CURRENT < SIZE # if CURRENT == 0 # undef CURRENT # define CURRENT 1 # elif CURRENT == 1 # undef CURRENT # define CURRENT 2 // ... # endif # include TARGET # include "repeater.h" #else #endif repeater.h define initial state self-include self-include target-include state-machine repeater.h(TARGET, SIZE)
  14. 14. #ifndef REPEAT_PARAM #define REPEAT_PARAM(n) class T ## n #endif template <class R, REPEAT(CURRENT, REPEAT_PARAM)> struct test_t {}; Vertical Repetition (cont.) 14 spec.h iteration count #define TARGET "spec.h" #define SIZE 3 #include "repeater.h" main.cpp set macro parameter call macro file function
  15. 15. Is it end? 15 template <class T0, class T1, class T2> struct tiny_size {}; template <class T0, class T1> struct tiny_size<T0, T1, none> {}; template <class T0> struct tiny_size<T0, none, none> {}; template <> struct tiny_size<none, none, none> {}; comma problem need to sub function seperate original template & partial specialization generator
  16. 16. COMMA_IF_NONZERO (helper) 16 #define COMMA_IF_NONZERO_0 #define COMMA_IF_NONZERO_1 , #define COMMA_IF_NONZERO_2 , #define COMMA_IF_NONZERO_3 , #define COMMA_IF_NONZERO_4 , #define COMMA_IF_NONZERO_5 , #define COMMA_IF_NONZERO(n) CONCAT(COMMA_IF_NONZERO_, n) all cases should be defined!
  17. 17. SUB (helper) 17 // ... #define SUB_33 0 #define SUB_20 2 #define SUB_21 1 #define SUB_22 0 #define SUB_10 1 #define SUB_11 0 #define SUB_00 0 #define SUB(a, b) CONCAT(CONCAT(SUB_, a), b) all cases should be defined ... ?
  18. 18. Vertical Repetition (cont.) • size ≠ limit 18 // ... #elif CURRENT < LIMIT # if CURRENT == 0 # undef CURRENT # define CURRENT 1 // ... repeater.h repeater.h(TARGET, SIZE, LIMIT)
  19. 19. Vertical Repetition (cont.) 19 main.cpp #define SIZE 3 template <class R COMMA_IF_NONZERO(SIZE) REPEAT(SIZE, REPEAT_PARAM)> struct test {}; #define TARGET "spec.h" #define LIMIT SUB(SIZE, 1) #include "repeater.h" template <class R COMMA_IF_NONZERO(CURRENT) REPEAT(CURRENT, REPEAT_PARAM)> struct test<R COMMA_IF_NONZERO(CURRENT) REPEAT(CURRENT, REPEAT_VAR) COMMA_IF_NONZERO(SUB(SIZE, CURRENT)) REPEAT(SUB(SIZE, CURRENT), REPEAT_NONE)> {}; spec.h file iteration generate partial specialization generate original template
  20. 20. Vertical Repetition (cont.) 20 • Local iteration: using macro state #if !defined(IS_REPEATING) # define IS_REPEATING 1 # include "repeater.h" #else # if !defined(CURRENT) # define CURRENT 0 # include "repeater.h" # elif CURRENT <= LIMIT // ... # else # undef IS_REPEATING # endif #endif initial state iterating state
  21. 21. Vertical Repetition (cont.) 21 #if !defined(IS_REPEATING) # define SIZE 3 template <class R COMMA_IF_NONZERO(SIZE) REPEAT(CURRENT, REPEAT_PARAM)> struct test {}; # define TARGET "test.h" # define LIMIT SUB(SIZE, 1) # include "repeater.h" #else template <class R COMMA_IF_NONZERO(CURRENT) REPEAT(CURRENT, REPEAT_PARAM)> struct test<R COMMA_IF_NONZERO(CURRENT) REPEAT(CURRENT, REPEAT_VAR) COMMA_IF_NONZERO(SUB(SIZE, CURRENT)) REPEAT(SUB(SIZE, CURRENT), REPEAT_NONE)> {}; #endif iterating state initial state repetition entry-point
  22. 22. boost pp • boost preprocess library – BOOST_PP_CAT – BOOST_PP_ENUM_PARAMS – BOOST_PP_REPEAT – BOOST_PP_COMMA_IF – BOOST_PP_SUB – BOOST_PP_DEC – BOOST_PP_WHILE – BOOST_PP_ITERATE 22
  23. 23. boost pp (cont.) • many predefined macros functions – Arithmetic, Logical, and Comparison Operations – Control Structures – Token Pasting(argument selection) – Data Types(sequence, tuple, array, list) • well-optimized expand complexity 23 # define BOOST_PP_NODE_ENTRY_256(p) BOOST_PP_NODE_128(p)(p)(p)(p)(p)(p)(p)(p) # define BOOST_PP_NODE_ENTRY_128(p) BOOST_PP_NODE_64(p)(p)(p)(p)(p)(p)(p) // ... # define BOOST_PP_NODE_ENTRY_2(p) BOOST_PP_NODE_1(p)
  24. 24. boost pp (cont.) • supports 256 reentrancy • supports 3 dimension (concurrently expandable count) 24 # define BOOST_PP_DEC_0 0 # define BOOST_PP_DEC_1 0 // ... # define BOOST_PP_DEC_255 254 # define BOOST_PP_DEC_256 255 # define BOOST_PP_REPEAT_1(c, m, d) BOOST_PP_REPEAT_1_I(c, m, d) # define BOOST_PP_REPEAT_2(c, m, d) BOOST_PP_REPEAT_2_I(c, m, d) # define BOOST_PP_REPEAT_3(c, m, d) BOOST_PP_REPEAT_3_I(c, m, d)
  25. 25. Summary • Don't repeat yourself! • reduce boilerplate code using preprocess programming • but, your compile time is also boosted! 25

×