C++ 템플릿 함수 짜는데 질문있습니다~

greathero의 이미지

int main(int argc, char** argv) { 
	BookWidget bw;
	doPro(bw);
	return 0;
}
 
template<typename T>
void doPro(T& pw) { 
	T pw2(50);
	T pw3;
	int a = 10;
 
	if(pw.size() > a) {
		std::cout << "OK" << std::endl;
	}
 
	if(pw != pw2) {
		std::cout << "OK2" << std::endl;
	}
 
	if(pw != pw3) { 
		std::cout << "ERROR" << std::endl;
	}
	else { 
		std::cout << "OK3" << std::endl;
	}
}

위와 같이 템플릿 개념 익힐겸 간단히 짜본 코드가 있습니다.
여기서 보면 연산자 >와 연산자 !=이 있는데요.
이걸 BookWidget.h에 아래와 같이 정의하였습니다.

class BookWidget: public Widget {
...
};
 
bool operator>(const Widget& lhs, const int rhs); // 멤버 함수로 놓지 않고 전역 함수처럼 쓰기 위해 이렇게 했습니다.
bool operator!=(const Widget& lhs, const Widget& rhs);

그리고선 BookWidget.cpp에 두개의 연산자에 대한 구현부 코드를 작성했습니다.
그런데, 컴파일을 할 때 doPro 함수에서 "pw.size() > a" <- 이 부분에서 제가 정의한 > 연산자를 자꾸 찾지 못하고 에러를 냅니다.
Namespace안에 연산자 >와 !=을 정의해놓고 using 연산자를 통해서 쓰면 잘 되긴 합니다만...

이렇게 Namespace를 명시하지 않고 전역으로 정의한 연산자를 자연스럽게 쓸 수 있는 방법은 없을까요?

kukyakya의 이미지

주어진 소스 코드만으로는 BookWidget::size의 반환 타입을 알 수가 없어 답변드리기 어려울 것 같습니다.

올리시는 질문들을 보면 템플릿에 관한 문제 이전에 아직 C++ 문법에 익숙하지 않으신게 아닌가 싶은데 템플릿없이 클래스를 짜보시는게 더 좋을 것 같습니다.

클래스 템플릿의 연산자에 대해선 클래스 내부에 friend로 선언&정의를 같이 하는 방법이 사용되는데, 이에 대해선 Effective C++ 서적에서 찾아보실 수 있습니다.

greathero의 이미지

일반 클래스의 연산자구요~
단지 일반 클래스를 템플릿 함수에 넘겨서
템플릿 함수에서 연산자를 써먹는 경우에 대해서 말씀 드리는거에요 ㅎㅎ

제 말을 잘못 이해하신거 같네요ㅠ

greathero의 이미지

코드가 뭐가 잘못 되었을까요?ㅠ

ifree의 이미지

함수를 템플릿으로 정의해 놓고 연산자는 특정한 instantiation 에 해당하는 경우만 정의해 놓으면, (네임스페이스를 들락 날락 해야 하는)문제가 생길 수 있습니다.
연산자도 같이 템플릿으로 정의해야 해요.

greathero의 이미지

template <typename T>
bool operator>(const T& lhs, const int rhs);
 
template <typename T>
bool operator!=(const T& lhs, const T& rhs);

이렇게 써봤는데 역시나 컴파일러가 이 연산자들을 찾지를 못하네요ㅠ
클래스에 속해있지도 않고 네임스페이스에도 속해있지 않으면 찾을 방법이 없는건가봐요...

그냥 클래스 내에 unary function처럼

class BookWidget {
public:
  bool operator>(const int rhs);
  bool operator!=(const T& rhs);
  ...
}

이런식으로 써야 되는걸까요ㅠ
ifree의 이미지

일단 오퍼레이터에 대한 이전의 비 템플릿 정의를 헤더에 같이 집어 넣어 컴파일해 보세요.
또는 포인터 변수에 대한 specilization 이 필요할 듯 합니다.

bool operator>(T0 t0, T1 t1)
{
    typename iterator_traits<T0>::value_type tmp = *t0;
    ...    
    return *t0 > *t1;
}
greathero의 이미지

//BookWidget.h
 
bool operator>(const Widget& lhs, const int rhs); 
 
bool operator!=(const Widget& lhs, const Widget& rhs);
 
template <typename T>
bool operator>(const T& lhs, const int rhs);
 
template <typename T>
bool operator!=(const T& lhs, const T& rhs);

헤더파일에 위의 코드를 넣어봤는데 여전히 컴파일러는 > 연산자와 != 연산자의 존재를 모르고있네요ㅠ
"pw.size() > a" <- 이 조건식에서 error C2446: '>' : 'int'에서 'Widget *'(으)로 변환되지 않았습니다. <- 에러가 이렇게 뜨는걸로 봐선...
확실히 연산자의 존재를 컴파일러가 알지 못해서 자꾸 원래의 > 연산자를 사용하려다가 에러가 나는거 같아요...

bool operator>(T0 t0, T1 t1)
{
    typename iterator_traits<T0>::value_type tmp = *t0;
    ...    
    return *t0 > *t1;
}

그리고 이 코드는 객체 타입으로 이터레이터를 넘겨서 쓰는 코드 같은데 갑자기 이런 코드를 왜 써야되는지 잘 이해가 가지 않아요ㅠ
조금 더 쉽게 설명해 주실 수 있을까요?
ifree의 이미지

선언이 아닌 실제 함수 정의를 모두 헤더 파일에 넣고 컴파일해 보시기 바랍니다.

greathero의 이미지

정말 미스테리네요...
풀소스를 한번 공개해볼테니 혹시라도 미심쩍은거 있으면 알려주세요ㅠ

Widget.h

#ifndef _WIDGET_H_
#define _WIDGET_H_
 
class Widget { 
public:
	Widget() { }
	virtual ~Widget() { }
 
	virtual Widget* size() = 0;
	virtual void normalize() = 0;
	virtual void swap(Widget& other) = 0;
	virtual int getS() const = 0;
};
 
#endif

BookWidget.h

#ifndef _BOOK_WIDGET_H_
#define _BOOK_WIDGET_H_
 
#include "Widget.h"
 
class BookWidget: public Widget {
public:
	BookWidget(): s(100) { }
	BookWidget(int n): s(n) { }
	virtual ~BookWidget() { } 
 
	virtual Widget* size();
	virtual void normalize();
	virtual void swap(Widget& other);
	virtual int getS() const;
private:
	int s;
};
 
bool operator>(const Widget& lhs, const int rhs) { 
	return (lhs.getS() > rhs);
}
 
bool operator!=(const Widget& lhs, const Widget& rhs) {
	if(lhs.getS() != rhs.getS())
		return true;
	return false;
}
 
template <typename T>
bool operator>(const T& lhs, const int rhs) { 
	return (lhs.getS() > rhs);
}
 
template <typename T>
bool operator!=(const T& lhs, const T& rhs) { 
	if(lhs.getS() != rhs.getS())
		return true;
	return false;
}
 
#endif

BookWidget.cpp

#include "BookWidget.h"
 
Widget* BookWidget::size() { 
	return this;
}
 
void BookWidget::normalize() { 
	// normalize
}
 
void BookWidget::swap(Widget& other) { 
	// swap
}
 
int BookWidget::getS() const { 
	return s;
}

main.cpp

#include "Widget.h"
#include "BookWidget.h"
#include <iostream>
 
template<typename T>
void doPro(T& w);
 
int main(int argc, char** argv) { 
	BookWidget bw;
	doPro(bw);
	return 0;
}
 
template<typename T>
void doPro(T& pw) { 
	T pw2(50);
	T pw3;
	int a = 10;
 
	if(pw.size() > a) {
		std::cout << "OK" << std::endl;
	}
 
	if(pw != pw2) {
		std::cout << "OK2" << std::endl;
	}
 
	if(pw != pw3) { 
		std::cout << "ERROR" << std::endl;
	}
	else { 
		std::cout << "OK3" << std::endl;
	}
}
klara의 이미지

pw.size()가 반환하는건 Widget*이므로 필요한 건 Widget*과 int를 비교하는 연산자입니다.

ifree의 이미지

템플릿이 자동으로 없는 연산을 만들어 주지는 않기 때문에,
일반적인 템플릿을 만들고, 원하시는 연산에 대한 Specialization 을 별도로 구현해 주어야 합니다.

greathero의 이미지

bool operator>(const Widget& lhs, const int rhs) {
return (lhs.getS() > rhs);
}

이거 아닌가요?;

DarkSide의 이미지

bool operator>(Widget* lhs, const int rhs) {
return (lhs->getS() > rhs);
}

klara의 이미지

포인터와 레퍼런스를 구분하세요.

DarkSide의 이미지

마지막에 허탈해지네요,
만드신 템플릿은 형식만 템플릿이 들어가 있지 템플릿이 들어가 있지, 내용은 그냥 함수랑 차이가 없네요.

greathero의 이미지

template<typename T>
void doPro(T& pw) { 
	T pw2(50);
	T pw3;
	int a = 10;
 
	if(pw.size() > a) {
		std::cout << "OK" << std::endl;
	}
 
	if(pw != pw2) {
		std::cout << "OK2" << std::endl;
	}
 
	if(pw != pw3) { 
		std::cout << "ERROR" << std::endl;
	}
	else { 
		std::cout << "OK3" << std::endl;
	}
}

이 부분 말씀하시는건가요?
그냥 함수랑 차이가 없다라고 말씀하신게 어떤걸 의미하는지 알려주시면 감사하겠습니다ㅠ

템플릿 암시적 인터페이스에 대해서 실험중이었던지라... 그걸 만족하는지에 대해 보는 코드였거든요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.