[완료] C++: 템플릿 함수로의 변환

dummytoguru의 이미지

Essential C++ 3.6절을 보다가 질문드립니다.
주어진 백터 중 특정한 값보다 작은 값만을 갖는 새로운 백터를 반환하는 함수인 less than()을 일반화해가는 것이 3.6절의 내용입니다.

이렇게 생긴 제한적인 코드가,

vector<int> less_than( const vector<int> &vec, int value )
{
        vector&ltint&gt nvec;
        for ( int ix = 0 ; ix &lt vec.size() ; ++x )
            if ( vec[ix] &lt value )
                  nvec.pushback( vec[ix] );
        return nvec;       
}

타입에 대한 의존성도 없고 백터에 대한 의존성도 없는 이런 코드 바뀝니다.

template&lttypename InputIterator, typename OutputIterator, 
	 typename ElemType,       // 비교할 값의 타입
	 typename Comp&gt           // 비교연산(predicate)의 종류
OutputIterator filter( InputIterator first, InputIterator last, OutputIterator at, const ElemType &val, Comp pred )
{
	while ( (first = find_if( first, last, bind2nd( pred, val ) )) != last )
	{
                // 무슨 일이 일어나는지를 확인하기 위해 콘솔에 출력
		cout &lt&lt "found value: " &lt&lt *first &lt&lt endl;
		// 값 대입 후 반복자 증가
		*at++ = *first++;
	}
	return at;
}

책은 정렬 후 원하는 조건에 해당하는 값이 처음 나타나는 요소부터 마지막 요소까지 삭제하는 아래와 같은 방법도 소개합니다.

vector<int> sub_vec( const vector<int> &vec, int val )
{
	vector<int> local_vec(vec);
	sort( local_vec.begin(), local_vec.end() ); 
 
	vector<int>::iterator iter = 
		find_if( local_vec.begin(), local_vec.end(), bind2nd( greater<int>(), val ));
        /////////////////!!!!!!!!/////////////////
	local_vec.erase( iter, local_vec.end() ); 
 
	return local_vec;
}

또한 이렇게 비템플릿 형태로 구현한 것을 템플릿 함수로 바꾸는 연습을 해보라고 권합니다.

설명이 길었네요.
///////////////!!!!!!!!/////////////// 이 부분이 바로 제가 궁금한 부분입니다.
앞의 filter() 의 경우 <algorithm>에서 제공하는 find_if()함수를 사용하는데 sub_vec()의 경우 컨테이너 멤버함수인 erase()를 사용합니다.
따라서 filter()는 배열의 주소나 벡터, 리스트 등의 컨테이너 반복자를 전달해도 되도록 일반화가 가능했지만 sub_vec()은 배열을 전달할 경우 erase()를 사용할 수 없게 되므로 일반화가 어려워보입니다.

sub_vec()의 백터에 대한 의존성을 없애려면 어떻게 해야하나요?

dummytoguru의 이미지

...로 감쌌더니 같은 표현을 & lt; & gt;로 고쳐야 되고, 인덴트도 안되길래 [code]...[/code]를 썼더니 이 보이질 않게 되네요. 고칠 수 있는 방법이 있나요?

winner의 이미지

그리고 그것이 Effective STL 의 항목 1(적재적소에 알맞은 container 를 사용하자) 과
항목 2(Container 에 독립적인 code 라는 환상을 조심하자) 입니다.
항목 2 에서는 아예 일반화교(?)에 빠진 당신이라는 말까지 하고 있죠.

반복자 category 가 제공되고 각 container 들의 interface 를 통일하는 이유는
완벽한 일반화를 위한 code 를 작성하는 것이 아닌 적절한 수준에서 일반화를 시키기 위함입니다.

임의접근반복자를 동일하게 제공한다고 해서 배열과 vector, deque 가 항상 동일하게 일반화된 algorithm
code 를 작성할 수 있는 것 또한 아닙니다.

물론 그런 고민은 자신이 작성하고자 하는 algorithm 의 요구조건을 최소화시켜 일반화수준을 향상시키는데
도움을 주지만 그 한계를 파악하는 것도 중요합니다.

-------------------------------------------------------------------------------------------------

서론이 길었는데 단도직입적으로 말해 제시된 code 는 배열과 어울리지 않습니다.
이럴 때 쓰는 방법은 template 특화 정도입니다.

dummytoguru의 이미지

제가 생각지 못한 방법으로 같은 문제를 해결한 분이 계신가 싶어서 질문드렸는데 역시 무리하게 일반화하려고 들면 안되는 거였군요.
이펙티브 STL을 아직 읽어보지 못했는데 보고 있는 Essential C++과 Accelerated C++을 얼른 마저 보고 읽어봐야겠습니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.