주의 : 공부하면서 정리한 것이기 때문에 오류가 있을 수 있습니다.


실습 과제 4-3 :


다음 코드에서 불필요한 인스턴스화를 제거하라.



수정된 메타함수들의 의미론이 수정되기 전과 동일한지를 점검하는 테스트들도 작성하라.




풀이 :


위의 문제들은 게으른 평가에 대한 이해도를 확인하는 문제이다. ::type 이나 ::value 가 불리는 순간 해당 템플릿은 인스턴스화된다. 그러므로 게으른 평가를 위해서는 메타함수들이 실제로 평가되지 않도록 ::type 이나 ::value 를 없애야만 한다. 물론 반드시 필요한데 호출하는 코드를 지워버린다면 에러가 나므로 주의해야 한다.


1. next_if 메타 함수.


일단 next_if 의 의미를 파악하자.


N 을 Predicate 함수에 적용한 결과가 true 이면

    mpl::next< N > 을 호출한 결과를 반환하고

그렇지 않으면

   N 을 그대로 반환한다.


mpl::next 는 다음과 같은 기능을 가지고 있다.


순차열 안의 다음 반복자( iterator )를 반환한다. [ 주의 : next 는 여러 개의 중복된 의미를 가지는데, 그것의 인자의 형식에 따라 다르다. 예를 들어 X 가 정수형 상수라면, next< X > 는 같은 형식의 증가된 정수형 상수를 반환한다. 이후의 명세는 iterator-specific 하다. 대안으로 선택할 수 있는 구문에 대한 세부적인 설명을 원한다면 관련 개념들의 문서를 참조하기 바란다. ]

http://www.boost.org/doc/libs/1_52_0/libs/mpl/doc/refmanual/next.html


'predicate' 는 '술어' 라는 뜻이기 때문에 mpl::if_ 의 조건을 결정하기 위한 서술문을 의미하는 메타 함수를 의미한다고 보면 될 것이다. 예를 들어 C++ 식으로 표현하면 다음과 같다; if( true == Predicate( N ) ){ ... }.


이를 테스트하기 위해서는 Predicate 를 평가해서 나온 ::type 이 가리키는 형식이 반드시 ::value 라는 멤버를 가지고 있어야만 한다. 그래서 다음과 같은 식으로 평가를 해 볼 수 있다. Predicate 의 형태를 보요 주기 위해서 메타 함수 클래스를 사용한 경우와 자리표 표현식을 사용한 경우의 두 가지 예제를 모두 보여 주겠다.



자 이제 이것을 게으른 평가가되도록 최적화해 보자.


현재 mpl::apply 메타 함수의 ::type 과 mpl::next 메타 함수의 ::type 이 불리고 있다. 책에서 배운 대로 mpl::identity 를 사용해서 제거해 보도록 하자.



안타깝게도 우리의 기대를 무참하게 짓밟아 버린다. 왜일까?


mpl::identity::type 은 그것의 매개변수로 들어 왔던 스칼라나 메타함수의 원형을 그대로 돌려 준다. 그러므로 아직까지는 mpl::identity< mpl::next< N > > 과 mpl::next< N > 이 평가되지 않은 상황이다. 이를 해결하기 위해서는 next_if2 : mpl::if_< ... >::type 으로 만들어 주거나 사용할 때 next_if2< ... >::type::type::value 를 통해 값을 가져와야 한다. 사용자들은 보통 ::type 을 한 번만 사용한다고 인지하고 있기 때문에 필자는 구조체 쪽에서 처리하는 방법을 택했다. 최종 코드는 아래와 같다.



사실 mpl::eval_if 를 사용하면 mpl::identity 를 사용할 필요가 없다. 물론 다들 알고 있겠지만 책에서 배운 내용을 점검해 보는 차원에서 위의 방식으로 풀어 보았다. 실제로 아래와 같이 매우 깔끔한 코드를 만들 수 있다.



2. formula 메타 함수.


mpl::not_equal_to 는 integral constant 에 대해서 적용되므로 N1 과 N2 가 integral constant 라는 것을 알 수 있다. 그러므로 formula 메타 함수는 다음과 같은 기능을 가지고 있다.


IF N1 과 N2 가 다르면

IF N1 이 N2 보다 크면

N1 에서 N2 를 뺀 결과 반환.

ELSE

N1 을 반환.

ELSE

N1 에 N1 에다 2를 더한 결과를 더한 결과 반환.


조금 복잡하기는 하지만 1 번과 크게 다를 것 없다. 일단 mpl::if_ 를 mpl::eval_if 로 바꾼다. 그리고 나서 mpl::eval_if 내의 메타 함수들에서 불필요한 ::type 을 제거한다.



+ Recent posts