예전 자유 게시판

C++ TMP 실습문제 2-1에 질문있습니다!

질문있습니다 2007-09-11 23:09

안녕하세요 (_ _)
평소에 류광님의 역서를 감명깊게 보고 있는 학생입니다.

그 중 최근에는 "C++ 템플릿 메타 프로그래밍"을 보고 있는데요.
인터넷에서 "실습과제 2-1"의 해법에 대한 의견 충돌이 있어서
도움을 구하고자 글을 남깁니다.

이 문제를 가지고 일주일 넘게 논쟁중이지만
아직도 의견 차이를 좁히지 못하고 있습니다.

두 소스다 틀린 답은 아닙니다만
어느쪽이 더 일반적인 해법인지 알려주시면 감사하겠습니다.

제 사견이 개입될 것 같아 소스의 설명은 생략하였습니다만
소스의 원 출처를 링크해두겠습니다.

소스1: http://blog.naver.com/neo_turing/20041187526
소스2: http://blog.naver.com/chyaya/130021759854


[실습과제 2-1]
아래의 예처럼, 임의의 복합 형식 c를 첫 번째 인수로 취하고
c에 있는 모든 형식 x를 형식 y로 치환하는 삼항 메타함수 replace_type<c, x, y>를 작성하라.

typedef replace_type< void*, void, int >::type t1; // int*
typedef replace_type<int const*[10], int const, long>::type t2; // long* [10]
typedef replace_type<char& (*)(char&), char&, long&>::type t3; // long& (*)(long&)


[소스1]
template<class PT>
struct CompoundType
{
       typedef const PT* type; // 기본형 PT를 이용해 임의의 복합 타입 정의
};

template<class C, class X, class Y>
struct replace_type
{
       BOOST_STATIC_ASSERT(( boost::is_same<CompoundType<X>::type, C>::value ));
       typedef typename CompoundType<Y>::type type;
};

[소스2]
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/add_reference.hpp>

// impl
template<class c, class x, class y, bool s>
struct replace_type_impl;

// select result
template<class c, class x, class y>
struct replace_type {
       static bool const _s = boost::is_same<c, x>::value;
       typedef typename replace_type_impl<c, x, y, _s>::type type;
};

// return all change result
template<class c, class x, class y>
struct replace_type_impl<c, x, y, true> {
       typedef y type;
};

// return no change result
template<class c, class x, class y>
struct replace_type_impl<c, x, y, false> {
       typedef c type;
};

// for pointer
template<class c, class x, class y>
struct replace_type_impl<c*, x, y, false> {
       typedef typename replace_type<c, x, y>::type *type;
};

// for reference
template<class c, class x, class y>
struct replace_type_impl<c&, x, y, false> {
       typedef typename replace_type<c, x, y>::type _t;
       typedef typename boost::add_reference<_t>::type type;
};

// for const
template<class c, class x, class y>
struct replace_type_impl<c const, x, y, false> {
       typedef typename replace_type<c, x, y>::type const type;
};

// for volatile
template<class c, class x, class y>
struct replace_type_impl<c volatile, x, y, false> {
       typedef typename replace_type<c, x, y>::type volatile type;
};

// for array
template<class c, class x, class y>
struct replace_type_impl<c[], x, y, false> {
       typedef typename replace_type<c, x, y>::type type[];
};

// for n array
template<class c, class x, class y, unsigned n>
struct replace_type_impl<c[n], x, y, false> {
       typedef typename replace_type<c, x, y>::type type[n];
};

// for void function
template<class r, class x, class y>
struct replace_type_impl<r (*)(void), x, y, false> {
       typedef typename replace_type<r, x, y>::type _r;
       typedef typename _r (*type)(void);
};

// for one parameter function
template<class r, class p, class x, class y>
struct replace_type_impl<r (*)(p), x, y, false> {
       typedef typename replace_type<r, x, y>::type _r;
       typedef typename replace_type<p, x, y>::type _p;
       typedef typename _r (*type)(_p);
};

// for two parameter function
template<class r, class p1, class p2, class x, class y>
struct replace_type_impl<r (*)(p1, p2), x, y, false> {
       typedef typename replace_type<r, x, y>::type _r;
       typedef typename replace_type<p1, x, y>::type _p1;
       typedef typename replace_type<p2, x, y>::type _p2;
       typedef typename _r (*type)(_p1, _p2);
};


류광 2007-09-12 19:09

논의가 너무 길어서 읽고 이해하려면 시간이 좀 걸릴 것 같습니다. 그나저나 짧은 버전은 그 자체로는 작동이 안 되는 것 같은데요? 그리고 긴 버전은 제가 가지고 있는 g++에서는 typename이 잘못 들어간 부분 때문에 컴파일이 안 됩니다.

문제가 요구하는 것은... 이를테면 답을 "replace_type.hpp"에 저장했다고 할 때 사용자가 #include "replace_type.hpp"만 하고 나면 다른 과정 없이 바로 replace_type을 사용할 수 있어야 합니다. 그런 측면에서 볼 때 짧은 버전은 답이라고 하기가 좀 그렇습니다.


참고로 다른 독자들의 해법도 한 번 보시길:
[ http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?CPPTM_Answers_-_Exercise_2-1 ]

류광 2007-09-12 19:09


그나저나 열심히 공부하시는 모습을 보니 기쁩니다... 오역 때문에 빚어진 논란이 아니길 바랄 뿐입니다.

질문있습니다 2007-09-13 17:09


답변 감사합니다. ^ -^
사실 긴버전을 제가 작성한 것이였는데 vc2005에서만 테스트를 해봤거든요.
이 기회에 g++도 설치해서 해봐야 할 것 같습니다.
그리고 부끄럽지만 아직도 탬플릿 매개변수의 종속 타입에 대해
typename 키워드를 붙이는 것이 자주 햇갈린답니다 - _-;;