예전 자유 게시판
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 키워드를 붙이는 것이 자주 햇갈린답니다 - _-;;