boost pp 20091102_서진택

33
boost day07 BOOST_PP 2009.11.02 서서서 , [email protected]

Upload: jintaek-seo

Post on 23-Feb-2017

260 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Boost pp 20091102_서진택

boost day07BOOST_PP

2009.11.02서진택 , [email protected]

Page 2: Boost pp 20091102_서진택

발표순서

• 문제제기• BOOST_PP 를 이용한 해결

Techniques 자체반복 구현

• Q&A

2

Page 3: Boost pp 20091102_서진택

문제제기

• 템플릿 프로그램을 할 경우 , 비슷한 패턴 의 코드를 되풀이 해서 작성해야 하는 상황 이 발생한다 .

– 델리게이트의 작성– 부분 특수화의 경우– 기타등등

3

Page 4: Boost pp 20091102_서진택

비슷한 패턴이 반복되는 상황

Page 5: Boost pp 20091102_서진택

가능한 해결책

1. 무시하고 되풀이되는 패턴을 되풀이 해서작성한다 .

2. 전처리기를 적절하게 활용한다 .3. BOOST_PP 를 활용한다 .

– Boost preprocessing library– 기계적으로 되풀이 되는 코드는 기계적으로 생

성하는 것이 마땅

5

Page 6: Boost pp 20091102_서진택

2 번째 해결책 : 전처리기를 적절하게 활용한다 .

Page 7: Boost pp 20091102_서진택

소스는 죽 ~ 이어집니다 .

Page 8: Boost pp 20091102_서진택

BOOST_PP 를 이용한 해결

• 전처리기 기본• 매크로

– object-like macro• #define 식별자 치환 - 목록

– function-like macro• #define 식별자 (a0,a1,…,an-1) 치환 - 목록

• 매크로 인수– , ( )

Page 9: Boost pp 20091102_서진택

• 매크로 인수– FOO( std::pair<int,long> ) // 인수 2 개– FOO({int x=1,y=2;return x+y;}) // 인수 2

개– FOO( (std::pair<int,long>) ) // 인수 1 개– FOO(({int x=1,y=2;return x+y;})) // 인수

1 개

9

, 를 전달할 때는 BOOST_PP_COMMA 를사용한다 .

Page 10: Boost pp 20091102_서진택

Technique

Page 11: Boost pp 20091102_서진택
Page 12: Boost pp 20091102_서진택
Page 13: Boost pp 20091102_서진택
Page 14: Boost pp 20091102_서진택
Page 15: Boost pp 20091102_서진택
Page 16: Boost pp 20091102_서진택
Page 17: Boost pp 20091102_서진택
Page 18: Boost pp 20091102_서진택

18

template<int x> struct int_ { static int const value = x; typedef int_<x> type; typedef int value_type; operator int() const { return x; } };

struct none {};

template<typename T0=none, typename T1=none, typename T2=none> struct tiny_size : int_<3> {};

template<typename T0, typename T1> struct tiny_size<T0,T1,none> : int_<2> {};

template<typename T0> struct tiny_size<T0,none,none> : int_<1> {};

template<> struct tiny_size<none,none,none> : int_<0> {};

모든 타입 파라미터에 대해 부분 특수화를

구현해야 한다 .

예 ) tiny_size 의 작성

Page 19: Boost pp 20091102_서진택

19

void main(){ std::cout << ods::tiny_size<int,int,int>::value << std::endl; std::cout << ods::tiny_size<int>::value << std::endl;//3//1// 계속하려면아무키나누르십시오 . . .}//main()

Page 20: Boost pp 20091102_서진택

template<class T0, class T1, class T1>

#define n 3template<BOOST_PP_ENUM_PARAMS(n,

class T)>

20

Page 21: Boost pp 20091102_서진택

21

struct none {};

template<typename T0=none, typename T1=none, typename T2=none> struct tiny_size : int_<3> {};

#define TINY_print(z, n, data) data

#define TINY_size(z, n, unused) \ template<BOOST_PP_ENUM_PARAMS(n, class T)> \ struct tiny_size< \ BOOST_PP_ENUM_PARAMS(n, T) \ BOOST_PP_COMMA_IF(n) \ BOOST_PP_ENUM( \ BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none) \ > \ : int_<n> {};

BOOST_PP_REPEAT( TINY_MAX_SIZE, TINY_size, ~ )

#undef TINY_size#undef TINY_print

수평 되풀이로 구현한예

n 이 1 인 경우의 확장 template<typename T0> struct tiny_size<T0,none,none> : int_<1> {};

Page 22: Boost pp 20091102_서진택

되풀이 방법

• 수평 되풀이– 전처리기 출력에서 같은 줄이 된다 .• 디버깅이 거의 불가능하다 .

• 수직되풀이– 지역반복

• 디버깅이 불편하다

– 파일반복• 사소한 코드 패턴에 대해 .hpp 파일을 만들어야 한

다 .– 자체반복 22

Page 23: Boost pp 20091102_서진택

예 ) 멤버함수 템플릿의 특수화구현

KSystemState::PostStateEvent() 의 기존구현

23

Page 24: Boost pp 20091102_서진택

24

class KSystemState{public: template<typename T> void _Push( const char* pszInEvent_, T inValue_ ) { std::cout << pszInEvent_ << ":" << inValue_ << std::endl; }//_Push()

template<typename T0> void PostStateEvent( const char* pszInEvent, T0 in0 ); template<typename T0, typename T1> void PostStateEvent( const char* pszInEvent, T0 in0, T1 in1 );};//class KSystemState

Page 25: Boost pp 20091102_서진택

25

template<typename T0>void KSystemStateEvent::PostStateEvent( const char* pszInEvent, T0 in0 ){ _Push( pszInEvent, in0 );}

template<typename T0, typename T1>void KSystemStateEvent::PostStateEvent( const char* pszInEvent, T0 in0, T1 in1 ){ _Push( pszInEvent, in0 ); _Push( pszInEvent, in1 );}

Page 26: Boost pp 20091102_서진택

26

KSystemStateEvent g_systemState;

void main(){ g_systemState.PostStateEvent( "Input", 0 ); g_systemState.PostStateEvent( "Output", 1, "dummy" );//Input:0//Output:1//Output:dummy// 계속하려면아무키나누르십시오 . . .}//main() 타입 인자를 2 개까지만 전달

할 수 있다 .

Page 27: Boost pp 20091102_서진택

자체반복 구현

• 반복 구현을 한 파일안에 작성

27

Page 28: Boost pp 20091102_서진택

28

#define POST_STATE_MAX_ARG 2

class KSystemStateEvent{public: template<typename T> void _Push( const char* pszInEvent_, T inValue_ ) { std::cout << pszInEvent_ << ":" << inValue_ << std::endl; }//_Push()

#define _POST_STATE_EVENT_TEMPLATE(z, n, unused) \ template<BOOST_PP_ENUM_PARAMS(n, typename T)> \ void PostStateEvent( const char* szInEvent_, BOOST_PP_ENUM_PARAMS( n, T ) );

BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_ADD(POST_STATE_MAX_ARG,1), _POST_STATE_EVENT_TEMPLATE, ~ )

#undef _POST_STATE_EVENT_TEMPLATE};//class KSystemStateEvent

선언과 body 를 별도로 구현 .

먼전 선언 부분을 간단하게 구현한다 .

Page 29: Boost pp 20091102_서진택

29

#ifndef BOOST_PP_IS_ITERATING

1) 반복을 호출하는 부분 작성

#else // #ifndef BOOST_PP_IS_ITERATING

2) 되풀이 되는 패턴을 제공하는 부분 작성

#endif // #ifndef BOOST_PP_IS_ITERATING

KSystemState.hpp 파일 작성

Page 30: Boost pp 20091102_서진택

30

#ifndef _KSYSTEMSTATE_INL#define _KSYSTEMSTATE_INL

#include <boost/preprocessor/repetition.hpp> #include <boost/preprocessor/arithmetic/sub.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp> #include <boost/preprocessor/iteration/iterate.hpp>

#define _POST_ARG(z, n, unused) BOOST_PP_CAT(T,n) BOOST_PP_CAT(In,n) #define _POST_PUSH(z, n, unused) _Push( pszInEvent, BOOST_PP_CAT(In,n) );

// generate specializations #define BOOST_PP_ITERATION_LIMITS (1, POST_STATE_MAX_ARG) #define BOOST_PP_FILENAME_1 "KSystemState.hpp" // this file #include BOOST_PP_ITERATE()

#undef BOOST_PP_FILENAME_1 #undef BOOST_PP_ITERATION_LIMITS

#undef _POST_PUSH #undef _POST_ARG

#endif // #ifndef _KSYSTEMSTATE_INL

1) 반복을 호출하는 부분

각각의 n 에 대해 자기자신KSystemState.hpp 를include 한다 .

Page 31: Boost pp 20091102_서진택

31

#define n BOOST_PP_ITERATION()

template<BOOST_PP_ENUM_PARAMS(n, typename T)> void KSystemStateEvent::PostStateEvent( const char* pszInEvent , BOOST_PP_ENUM( n, _POST_ARG, ~) ) { BOOST_PP_REPEAT( n, _POST_PUSH, ~ ) }

#undef n

2) 되풀이 되는 패턴을 제공하는부분

각각의 n 에 대해 (n 이 1, 2 일 때 ) 확장된다 .

Page 32: Boost pp 20091102_서진택

32

#define POST_STATE_MAX_ARG 4

class KSystemStateEvent{…};//class KSystemStateEvent

#include "KSystemState.hpp"

KSystemStateEvent g_systemState;

void main(){ g_systemState.PostStateEvent( "Input", 0 ); g_systemState.PostStateEvent( "Output", 1, "dummy", 1.2f, 0xff );//Input:0//Output:1//Output:dummy//Output:1.2//Output:255// 계속하려면아무키나누르십시오 . . .}//main()

이제 자유롭게 아규먼트의 개수만 정의하면 됩니다 ^^;

Page 33: Boost pp 20091102_서진택

참고문헌

• David Abrahams, “C++ Template Metaprogramming”, 정보문화사 , p.323

• http://agile.egloos.com/5026291• http://www.boost.org/doc/libs/

1_38_0/libs/preprocessor/doc/index.html

33