AcceleratedC++/Chapter7 | AcceleratedC++/Chapter9 |
~cpp ex) union(A, B) { return A+B; } union(A:string, " is...") (O), concaternate("COL", " is...") (X)그렇다면 어떻게 함수가 어떠한 자료구조를 만족 시키는지 판단할 수 있는가?
~cpp //median.h #ifndef GUARD_median_h #define GUARD_median_h #include <algorithm> #include <stdexcept> #include <vector> using std::domain_error; using std::sort; using std::vector; template <class T> // type 매개변수의 지정, 이 함수의 scope안에서는 데이터 형을 대신한다. T median(vector<T> v) { typedef typename vector<T>::size_type vec_sz; // typename에 대해서 알자 vec_sz size = v.size(); if (size == 0) throw domain_error("median of an empty vector"); sort(v.begin(), v.end()); vec_sz mid = size/2; return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid]; // double, int에는 유효, string은 operator / 가 없기 때문에 무효 } #endif실제 컴파일시 컴파일러는 프로그래머가 지정한 타입으로 이 함수를 인스턴스화 시켜서 생성하고 바인딩한다.
find(B, E, D) | D의 인자료 [B, E)를 비교하여 값을 찾는다. 비교를 하는 것은 크게 문제되지 않는다. |
accumulate(B, E, D) | D의 인자의 형을 기준으로 [B, E)를 비교하여 값을 모은다. 리턴값이 D의 자료형에 영향을 받기 때문에 문제의 발생소지가 존재한다. |
~cpp ex) accumulate(v.begin(), v.end(), 0.0); // 만약 0:int를 사용했다면 올바른 동작을 보장할 수 없다.
~cpp template <class T> T max(const T& left, const T& right) { return left > right ? left : right; }인자로 받은 두 값의 타입이 완전히 같아야지만 올바른 동작을 보장받는다. 인자는 operator>(T, T)를 지원해야한다.
find(c.begin(), c.end(), val) | 일반적인 함수의 작성 가능. 반복자를 통해서 반복자가 제공하는 방식으로 동작가능 |
c.find(val) | 특정형의 인스턴스인 c를 통해서만 접근가능. 내장배열에 적용 불가능 |
find(c, val) | 범위 지정이 불가능하고, 유용성이 첫번째의 경우보다 적다. |
~cpp template <class In, class X> In find(In begin, In end, const X& x) { while(begin != end && *begin != x) ++begin: return begin; }find 구현 2
~cpp template <class In, class X> In find(In begin, In end, const X& x) { if (begin == end || *begin == x) return begin; begin++; return find(begin, end, x); }상기 2개의 구현 모두 begin, end iterator를 순차적으로 접근하고 있음을 알 수 있다. 상기의 함수를 통해서 순차 읽기-전용의 반복자는 ++(전,후위), ==, !=, *를 지원해야한다는 것을 알 수 있다. 덧 붙여서 ->, .와 같은 멤버 참조 연산자도 필요로하다. (7.2절에 사용했떤 연산자이다.)
~cpp template <class In, class Out> Out copy(In begin, In end, Out dest) { if (begin != end) *dest++ = *begin++; return dest; }class In 형의 반복자는 함수가 진행되는 동안 반복자를 통해서 읽기 연산만을 수행한다. class Out 형의 반복자는 *dest++ = *begin++; 의 연산을 통해서 쓰기 연산을 수행한다. 따라서 class Out 반복자는 ++(전,후위). = 연산자만을 평가할수 있으면 된다.
~cpp template <class For, class X> void replace(For begin, For end, const X& x, const X& y) { while (beg != end) { if (*beg == x) *beg = y; ++beg; } }[begin, end) 의 범위안에서 x를 찾아서 y로 치환한다.
~cpp template <class Bi> void reverse(Bi begin, Bi end) { while (begin != end) { --end; if (begin != end) swap(*begin++, *end); } }begin 과 end 의 요소를 비교하여 다르다면 swap()시킨다.
~cpp template <class Ran, class X> bool binary_search(Ran begin, Ran end, const X& x) { while (begin < end) { Ran mid = begin + (end - begin ) /2; if (x < *mid) end = mid; else if (*mid < x) begin = mid + 1; else return true; } return false; }참고자료) Binary_search바이너리 서치
condition p:iterator, q:iterator, n:integer |
p+n, p-n, n+p, p+q, pn, p<q, p>q, p<=q, p>q |
~cpp c.end() == c.begin() + c.size() // this is true
~cpp vector<int> v; copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v)); //istream_iterator<int> 는 end-of-file, 에러상태를 가리킨다.C++의 모든 입출력 연산은 타입 지정연산이다. cin>>s.midterm>>s.final>>s.homework; 에서도 타입에 따라서 다른 일을 한다.
~cpp #include <algorithm> #include <cctype> #include <string> using std::find_if; using std::string; using std::isspace; inline bool space(char c) { return isspace(c); } inline bool not_space(char c) { return !isspace(c); } template <class Out> // changed void split(const string& str, Out os) { // changed typedef string::const_iterator iter; iter i = str.begin(); while (i != str.end()) { // ignore leading blanks i = find_if(i, str.end(), not_space); // find end of next word iter j = find_if(i, str.end(), space); // copy the characters in `[i,' `j)' if (i != str.end()) *os++ = string(i, j); // changed i = j; } }