원문 : http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_3-4

정보 : C++ Template MetaProgramming 실습 과제 3-4 의 풀이를 잘 이해할 수 있는 보충 자료라 생각해 번역해 봅니다. 논쟁이 참 재밌고 도움이 됩니다.

주의 : 번역이 개판이므로 원문을 참조하세요.

주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.

주의 : 가독성을 높이기 위해 잘 알려지거나 우리말과 발음이 비슷한 용어는 한글로 표기합니다.


CPPTM Answers - Exercise 3-4







명시적인 lambda 호출이 왜 필요한지 설명해 줄 수 있는 사람이 있나요? 나는 twice 안에 내포된 apply 가 add_pointer 자리표 표현식을 다룬다고 생각했는데, GCC 3.3.3 은 다음과 같이 하면 컴파일 에러를 내네요 :



아는 사람? -- Matt Brecknell




3.3 절은 왜 그것이 동작하지 않는지에 대한 좋은 설명을 제공합니다 - Ariel




Matt : 3.3 절은 책의 이전 절에서의 twice 메타 함수가 자리표 표현식을 직접적으로 사용하지 않는 이유에 대해서 설명합니다. 그러나 그리고 나서 3.3.2 절은 mpl::apply 에 대한 첫 번째 인자는 모든 lambda 표현식이 될 수 있다고 이야기합니다( 자리표로 만들어진 것들을 포함해서 말이죠 ). 당신의 twice 정의는 mpl::apply  를 사용해서 인자로 넘어 오는 메타 함수를 호출하기 때문에, 나는 mpl::lambda 를 사용하지 않고도 자리표 표현식을 사용할 수 있다고 기대했습니다. 예를 들어 나는 다음 코드가 당신의 twice 정의를 사용해 동작할 것이라고 믿습니다( 비록 나는 그 시점에 MPL 이 가능한 컴파일러를 사용하고 있지 않아서 검사해 볼 수 없었지만 말이죠 ) :



I'm currently working on the theory that the problem with my version of the nested invocation of twice might be something to do with the way the outer twice is evaluating placeholders in the inner twice, but I haven't figured it out yet. -Matt




당신의 이전 코드 예제에서, 먼저 안쪽의 twice 를 생각해 보세요. 그리고 두 번째 인자를 생각해 보세요. 그것은 단지 _1 입니다. 그것은 안쪽 twice 에서는 특별한 의미가 없습니다. 그러므로 안쪽 twice 의 결과는 _1**  입니다. 안쪽 twice 는 메타 함수이지, lambda 표현식이 아닙니다. 그러므로 당신은 mpl::apply 를 적용할 수 없습니다. 만약 mpl::lambda 를 boost::add_pointer 에 사용하게 된다면, 안쪽 twice 는 그것을 lambda 표현식을 생성하는데 사용할 것이고, 그 표현식은 mpl::apply 로 넘겨질 수 있습니다. 그리고 결국 바깥쪽 twice 에 넘어 갈 수 있습니다. 적어도 내가 생각하기에는 그것이 작동 방식입니다( 나는 Dave 가 이를 명확하게 설명할 수 있는지 궁금하군요 ) - Ariel




만약 내가 직접적으로 twice<> 를 ::type 과 함께 평가했다면, 나도 안쪽  twice<> 가 _1** 로 평가될 것이라는 데 동의합니다. 그렇지만 나는 그렇게 하지 않았기 때문에, 나는 바깥쪽 twice<> 가 안쪽 twice<> 를 자리표 표현식으로 취급할 것이라고 생각했습니다( 그리고 당신이 제시했듯이 그냥 메타 함수로 취급하지 않을 것이라 생각했습니다 ). 그러므로 나는 안쪽 twice<> 안의 mpl::apply 가 boost::add_pointer< _1 > 을 메타 함수 클래스로 변환하고, 반면에 두 번째 인자( bare _1 )를 바깥쪽 twice<> 에 대해 대체( substitute )하기 위해 남겨둘 것이라 기대했습니다.그것이 내가 _1 을 두 자리에 모두 사용한 이유입니다. 그것들이 서로 다른 문맥에서 서로 다른 것들을 가리키고 있음에도 불구하고 말이죠.  In any case, I don't see why your reasoning would apply to my formulation, without also applying to yours. 무엇보다도 당신은 당신의 버전에서 "_" 자리표를 같은 위치에 가지고 있습니다. 단 하나의 주요한 차이는 당신이 boost::add_pointer< _ > 를 mpl::lambda<> 안에 래핑했다는 것 뿐입니다. 나는 mpl::lambda 가 안쪽 twice<> 로 하여금 바깥쪽 twice<> 를 위한 "lambda 표현식을 생성"하도록 만든다는 것에 대한 당신의 근거에 동의할 수 없습니다 : 만약 안쪽 twice<> 가 자리표 표현식이라면, 그것은 이미 lambda 표현식입니다( 책 3.6 절 ). 명백히 내 근거가 다소 잘못되기는 했지만, 나는 여전히 당신이 제시한 근거들을 이해할 수 없습니다. - Matt




나는 안쪽 twice 가 자리표 표현식이라고 받아들였습니다. 그리고 나서 바깥쪽 twice 는 ( 각 mpl::apply 를 위한 ) 형식을 위해 두 자리표들을 대체합니다. mpl::lambda 를 사용하는 것은 boost::add_pointer 를 위한 자리표가 대체되는 것을 막습니다. 이것이 정확히 어떻게 동작하는 지는 잘 모르겠군요 - Ariel.




twice< twice< add_pointer< _1 >, _1 >, int > 가 작동하지 않는 이유는 다음과 같습니다. 명확한 영역 특수화를 하지 않으면 mpl::apply< twice< add_pointer< _1 >, _1 >, int >::type 은 다음과 같습니다.



이것은 매우 잘못 되었습니다. http://thread.gmane.org/gmane.comp.lib.boost.devel/115924 에서 진행중인 명시적 영역지정( scoping )을 사용하면, 제대로 작동하는 한 줄 표현은 다음과 같습니다.



명확히 이해하는데 도움이 되었으면 합니다. People/Aleksey Gurtovoy.


+ Recent posts