C++ (partial) template specialization 질문입니다.
글쓴이: aeronova / 작성시간: 일, 2006/08/13 - 8:01오전
안녕하세요,
제가 template specialization을 하다가 막혀서 질문드립니다.
일단 기본 template 함수는 다음과 같구요,
template<typename T1, typename T2> void printDebugMSG(const T1& msg1, const T2& msg2) { std::cout << msg1 << " : " << msg2 << std::endl; }
이것을 다음과 같이 typedef로 정의한 Matrix type의 경우 다르게 처리하려고 합니다.
typedef std::vector<double> Row; typedef std::vector<Row> Matrix;
첫번째 인자는 상관없고, 두번째 인자가 Matrix type인 경우를 하려고 하니 어떻게 해야 할 지 몰라서 일단 첫번째 인자도 const char*라고 두었습니다.
template<> void printDebugMSG<const char* msg1, const Matrix& matrix>(const char* msg1, const Matrix& matrix) { std::cout << "TEMPLATE SPECIALIZATION" << std::endl; }
이제 다음과 같은 예제를 이용하면
Matrix matrix; printDebugMSG("Hello","World"); printDebugMSG("Hello",matrix);
... 무수한 해독 불가능한 에러들이 쭉~ 뜹니다.ㅜㅜ
debug.h:26: error: missing `>' to terminate the template argument list debug.h:26: error: expected init-declarator before "const" debug.h:26: error: expected `;' before "const" debug.h: In function `void printDebugMSG(const T1&, const T2&) [with T1 = char[6 ], T2 = Matrix]': debugTest.cpp:8: instantiated from here debug.h:22: error: no match for 'operator<<' in 'std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)(+ std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<cha r, std::char_traits<char> >&)(&std::cout)), ((const char*)msg1)))), ((const char *)" : ")) << msg2' d:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/ostre am.tcc:63: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic _ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>&(*)(st d::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_tr aits<char>] d:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/ostre am.tcc:74: note: std::basic_ostream<_CharT, _Traits>& std::basic _ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>&(*)(std::b asic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<cha r>] .....
저는 "no match for 'operator<<'"를 보고 혹시나 싶어서 template과 관련된 모든 <,>에 간격을 주어 보았는데, 별 소득이 없었습니다. :(
조언 부탁드립니다.
Forums:
Beforetemplate<>void
Before
After
debug이면 std::cout보다는 std::cerr를 쓰시지요.
저라며는
이쯤 해 주면, 다들 좋아합니다.
___________________________________
Less is More (Robert Browning)
___________________________________
Less is More (Robert Browning)
많은 것을 보여
많은 것을 보여 주셔서 감사합니다. 덕분에 많은 것을 배웠습니다. :)
그런데,
1. 만일 인자 2개 다 특정 type을 가진 경우, template specialization을 어떻게 하는지 알고 싶습니다. 음... 예제 따라서 한다고 했는데, 제가 따라한 예제는 인자가 1개인 경우였거든요. 그래서 아마
이라고 사용된 듯 합니다. 저는 단순히 인자가 2개 모두 특정 type인 경우도 이와 동일하고 사용할 수 있다고 생각했는데, 생각처럼 잘 되질 않더군요.
2. 그리고, 보여주신 예제에 대한 설명 좀 부탁드립니다. struct을 public class로 사용해서 아예 debug 출력을 담당할 class를 만드신 것처럼 보입니다. 근데 인자 2개을 받는 constructor, 그러니까
이 함수의 경우, debug_msg_ class에 함수형이 선언되지 않았는데, 이렇게 class 외부에 정의될 수 있는지요? "inline" 때문에 자동적으로 class안에서 처리되기 때문인가요?
그리고 생각해보니 debug 용 class는 function object의 형태로 구현해 주어도 될 듯 합니다. 이게 더 나은 방법일까요? 다시 조언 부탁드립니다.
It's better to burn out than to fade away. -- Kurt Cobain.
1.template <typename T>void
1.
2. debug_msg ctor아닙니다. 그냥 global function입니다.
- 의문 날 때 test program 짜서 돌려 보세요.
- 누가 친절하게 아리켜 주지 않기도 하고 10중 8,9는 스스로 답을 알 수 있읍니다.
- 하드웨어나 기타 공학 과학은 실험하는 데에 돈과 시간이 들지만 소프트웨어는 얼마나 쉽습니까?
__________________________________
Less is More (Robert Browning)
___________________________________
Less is More (Robert Browning)
void foo(const char* s,
보여주신 이 함수는 template specialization이 아니라 그냥 일반 함수이지 않나요?
제가 template 부분을 따로 헤더로 만들어 필요한 클래스 헤더에 include해서 쓰고 있어서,
이렇게 일반 함수로 처리하면 mutiple definition error가 날 듯 합니다.
그리고 debug_msg_ 를 public class로 생각한 것은 다음과 같은 constructor 부분때문이었습니다.
이런 건 class에서만 가능하지 않나요?
- 의문 날 때 test program 짜서 돌려 보세요. - 누가 친절하게 아리켜 주지 않기도 하고 10중 8,9는 스스로 답을 알 수 있읍니다. - 하드웨어나 기타 공학 과학은 실험하는 데에 돈과 시간이 들지만 소프트웨어는 얼마나 쉽습니까? 저는 생각하시는 것처럼 그냥 별 생각 없이 질문만 올리지 않습니다. 보여주신 일반 함수로 처리하는 방법도 이미 이것 저것 하다 template 형식을 포기하고 사용해 보았지만, 이 함수 정의 부분이 여러 class에 포함될 경우 에러를 만나서 template 형식을 유지하면서 할 방법을 알고 싶어서 재질문을 올렸던 것입니다. 제가 참고한 곳은 C++ FAQ의 template 부분(http://www.parashift.com/c++-faq-lite/templates.html#faq-35.7)으로 여기 보면 예제로 인자 하나인 함수의 template specialization을 보여주어서 따라했습니다. 근데 제 경우는 인자가 2개라서 단순히 흉내니 에러가 나더군요. :(
p.s.
그리고 추천해주신 std:cerr에 관해 찾아보니 std::clog가 있어서 이걸 쓰기로 했습니다.
It's better to burn out than to fade away. -- Kurt Cobain.
이렇게 일반 함수로
>> 이렇게 일반 함수로 처리하면 mutiple definition error가 날 듯 합니다.
분명 그 함수는 중복정의 에러납니다.
그런데 왜 헤더에 정의할 수 있는 게 템플릿만 있다고 생각하시죠?
inline만 붙이면 됩니다.
얘는 ctor 맞습니다.
여러 가지 테스트를 하셨다니
제 말이 억울하셨을 수도 있겠군요.
미안합니다.
하지만 debug_msg()에 대한 질문은
아직도 무슨 뜻인지 이해를 못하겠군요.
___________________________________
Less is More (Robert Browning)
___________________________________
Less is More (Robert Browning)
inline으로 처리하면
inline으로 처리하면 각각 호출된 class 안에 함수가 embed되어서 template 비슷하게 쓰일 수 있군요.
저는 inline이 단순히 performance 개선용으로 사용되는 줄 알았는데, 덕분에 다른 용도를 배웠습니다.
그리고 자세히 보니, debug_msg()를 struct으로 처리해서 단순히 member data만 초기화시키고, 이걸 template global 함수에서 부르면서 "operator <<"으로 다양한 type의 인자를 처리하는 방식이군요. 이런 방식에 익숙치 않아 선뜻 이해를 못했습니다. 예제 감사드립니다.
It's better to burn out than to fade away. -- Kurt Cobain.
thyoo님이 다 설명해
thyoo님이 다 설명해 주셨으니 저는 왜 처음 코드가 잘못인지만 설명드리죠.
(2)는 (1)의 specialization이 될 수 없습니다. (1)의 첫번째 인자는 참조형인데 (2)는 그렇지 않기 때문입니다.
그럼 (2)를 참조형으로 고치면 되겠는데, 그렇게 하면 다른 문제가 발생합니다.
만약 (2)를 호출하는 코드가
라면 첫번째 인자의 형은 const char[6]이므로
로 하면 됩니다. 이제 문제는 "Hello"가 아닌 "Hi" 등으로 호출하면 첫번째 인자의 형이 달라지기 때문에
(2')가 아니라 (1)이 호출된다는 것입니다. 범용성이 없어지는 거죠. 이것은 참조형 인자를 받는 함수 템플릿을
string literal로 호출할 때 헷갈리기 쉬운 문제입니다.
또다른 예로
답변 감사합니다.
답변 감사합니다. 넘겨주는 인자의 type이 pointer인지 reference인지에 따라 다르게 인식되는 문제가 핵심이었군요. 주의해야겠습니다.
It's better to burn out than to fade away. -- Kurt Cobain.
댓글 달기