원문 : How Do Those Funky Placeholders Work?


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

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

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


MPL 을 하다가 보면 가장 이해가 안 되는 것이 자리표 표현식( placeholder expression )이다. 아주 간단한 형태의 자리표 표현식같은 경우에는 그나마 이해가 가지만, 조금만 복잡해져도 정신이 안드로메다로 가 버린다.


"C++ Template Metaprogramming" 의 내용 중에 다음과 같은 코드가 있다. 이해가 가는가? 



나름 자리표 표현식에 대해서 이해했다고 생각했었는데, 필자도 쉽게 이해할 수가 없었다. 그래서 공부도 하는 겸해서 자리표 표현식과 관련한 글을 번역해 보기로 했다.




How Do Those Funky Placeholders Work?


요즘 C++ 표준 함수 binder 들은 정말로 사용하기 어렵다. Chris Gibson 은 Boost 의 대안의 비밀을 보여 준다. 그것은 더욱 낫고 마법같다.


새로운 코딩 기법에 대해서 배우고 그것을 작업하면서 사용하려고 할 때마다, 부서 전반에서 그것이 얼마나 빠르게 받아들여지는지 확인하는 것은 흥미롭다. 널리 전파되는 가장 빠른 것 중의 하나는 boost bind 라이브러리이다. 표준 파이브러리의 bind1st 나 bind2nd 적응자( adapter )들보다 훨씬 사용하기 수비고 훨씬 유연하다. 일단 재미있게 보이는 자리표( placeholder )를 이해하게 되면, bind 라이브러리는 사용하기에 우아하고 단순하다. 그리고 초기의 노력이 보상받게 된다. 당신의 코드는 깔끔해지며, 이해하기 쉬워지며, 빠르게 검토하기 쉬워지며, 빠르게 테스트할 수 있게 된다. 그것은 버그를 포함할 가능성이 더 적으며 아마도 더욱 효율적일 것이다.


내 경험상 평균적인 개발자들은, 물론 당신을 말하는 것은 아니고 나는 확실히 아니다, bind 라이브러리를 처음 사용할 때 아마도 너무 많거나 너무 적거나 잘못된 자리표를 사용할 것이다; 그리고 적어도 한 군데는 잘못된 위치에 그것들을 배치할 것이다. 이런 것들은 여러 페이지의 컴파일 에러들을 발생시킬 것이다. 그리고 나서 평균적인 개발자들은 그것이 너무 어렵다고 생각해서 템플릿은 악마의 조화라고 판단할 것이다. 그리고 그들은 매뉴얼을 읽는데 시간을 소비하지 않고, 그저 그것이 작동하기만을 원할 것이다. So they hand code a solution instead and decide to do it properly before review or release, which in all probability never happens.


그러므로 나는 bind 라이브러리가 직관적인지 그렇지 않은지 판단할 수 없다. 일단 이해하고 나면 직관적이다. but doesn't intuitive mean you don't need to get the hang of it? Can it be true that the more you use the bind library the more intuitive it gets?


일단 개발자들이 그것을 이해하고 나면 언제나 다음과 같이 질문한다. "그런데 그 멋진 자리표는 어떻게 작동하는 거죠?". 이상적인 세계에서는 당신은 라이브러리의 세부사항을 구현하는 것에 관심을 가지지 않을 것이며, 당신은 그냥 그것을 사용하면 될 것이다. 그러나 무대 뒤에서 무슨 일이 벌어지고 있는지 이해하는 것은 몇 가지 이유때문에 유용하다. 당신이 오타를 쳤을 때 평균적인 컴파일러가 제공하는 에러 메시지를 확인하면, 어떤 일들이 벌어지고 있는지 이해하는 데 큰 도움이 된다. 두 번째로 전문가에 의해 개발된 설계를 공부하는 것은 항상 유익하며 당신의 설계를 개선하는데 도움이 될 수 있다. 마지막으로 거의 대부분의 개발자들은 당연히 호기심이 많고, 자리표 구문을 마음에 들어 하면 보통 그것이 작동하는 방식에 대해 알기를 원한다.


이 기사에서는 bind 라이브러리의 자리표가 작동하는 방식에 대해 설명하려고 하는데, 매우 기본적인 bind 라이브러리를 만들 것이다. 그것은 그다지 대단하지 않을 것이지만, 당신의 궁금증을 만족시켜주기에는 충분할 것이라 생각한다. 예제들은 무엇보다도 명확성을 중시하며, 효율성, const 정확성, volatility 등과 같은 다른 이슈들은 고려되지 않는다. 함수 반환 형식들도 고려되지 않으며 void 라고 가정된다는 것에 주의하라.


A quick recap


당신이 widget 컬렉션을 가지고 있으며 당신은 각각에 대해 어떠한 동작을 수행하기를 원하고 있다고 가정하자; 당신은 단순히 다음과 같이 작성할 것이다 :



for_each 알고리즘은 단항 함수( unary function )를 세 번째 매개 변수로 취하는데, 그것은 범위 내의 각 반복자( iterator ) 당 한 번씩 호출되며, 참조해제된 반복자( 역주 : 반복자가 참조하고 있는 실제 값 )를 단항 함수의 단일 인자로 넘긴다( 아래를 보라 ). 우리의 대상 함수는 세 개의 매개 변수를 가지는데, 그것은 두 개의 문제를 가지고 있다 :


  • 단항 함수와 대상 함수의 매개 변수의 개수가 다르다.
  • 참조해제된 반복자는 대상 함수의 매개 변수 중의 어떤 것에라도 사상될 수 있다.



매개 변수의 개수가 다른 문제를 해결하는 것은 소프트웨어 공학의 근본 정리( Fundametal Theory of Software Engineering )을 적용하고 알고리즘과 대상 함수 간에 간접층( level of indirection )을 추가함으로써 수행된다. 간접층은 오브젝트의 형태를 취하며, 그것을 바인더( binder )라고 부르도록 하자. 바인더의 역할은 대상 함수의 인터페이스를 호출하는 알고리즘의 인터페이스를 받아들이는( adapt ) 것이다. 바인더는 for_each 에 의해 호출될 수 있다. 왜냐하면 그것은 단항 연산자 () 를 가지고 있기 때문이다. 그리고 바인더는 대상 함수를 호출할 수 있다. 왜냐하면 그것은 대상 함수에 대한 포인터와 두 개의 부가적인 인자를 생성자에서 공급받기 때문이다.


DoSomething 의 세 매개 변수들 중의 어떤 것이 widget 이어야 하는지 지정하는 것이 자리표가 오게 되는 곳이다. bind 라이브러리를 사용해서 우리는 이를 단순화할 수 있다 :



bind 함수는 네 개의 인자들을 받는다 : 대상 함수인 DoSomething 의 주소, Gadget 오브젝트, Gizmo 오브젝트, 자리표 _1. bind 에 대한 두 번째, 세 번째, 네 번째 인자의 순서는 대상 함수에 대한 인자의 순서와 같다는 데 주목하라. 자리표는 for_each 에 의해 단항 함수에 넘겨지는 인자의 위치를 지시한다. 만약 DoSomething 의 시그너쳐( signature )가 widget 을 두 번째 매개 변수로 기대했다면, 우리는 다음과 같이 작성해야할 것이다 :




















+ Recent posts