라이브러리 4.1 표준 템플릿 라이브러리 표준 템플릿 라이브러리(Standard Template Library, STL)는 기본 라이브러리 Alex Stepanov,David Musser가 만든 STL대부분은 C++표준 라이브러리의 일부가 됨 Matt Austern 은 STL의 핵심 개발자 Josuttis는 라이브러리 튜토리얼을 작성 도입 예제 컨테이너는 개체를 포함하는 클래스 대표적을 vector와 list 클래스가 있다. std::vector vec; std::list lst; double vec_sum = std::accumulate(begin(vec), end(vec), 0.0); double lst_sum = std::accumulate(begin(lst), end(lst), 0.0); 반복자 ..
3.10 가변 템플릿(Variadic Template) 가변 템플릿은 ...으로 표시된 줄임표 연산자를 사용 왼쪽에 ... 연산자가 있으면 패킹 오른쪽에 ... 연산자가 있으면 언패킹 typename ...P : 복수의 타입 인수를 타입 팩 P에 패킹 : 클래스나 함수템플릿을 인스턴스화 할때 P를 언패킹 P ...p : 변수 팩 p에 여러 함수 인수를 패킹 sum(p...) : 변수 팩 p를 언패킹하고 여러 인수로 sum함수 호출 리턴타입은 첫번째 인수의 타입으로 정해짐 template inline T sum(T t) { return t; } template inline T sum(T t, P ...p) { return t + sum(...p); } auto s = sum(-7, 3.7f, 9u, -2...
3.9 람다(Lamda) (c++11) //함수를 인수로 즉시 전달할 수 있다 fin_diff([](double x) {return sin(x) + cos(x);}, 1., 0.001) //람다 표현식을 재사용하기 위해 변수에 저장할 수도 있다. auto sc_l = [](double x) { return sin(x) + cos(x); } //리턴타입을 명시적으로 선언하고자 한다면 [](double x) -> double { return sin(x) + cos(x); } 캡처 람다 표현식은 자체 매개변수 또는 이전에 캡처된 매개변수만 사용 가능 //람다를 매개변수화 할때 단순한 연산을 삽입 가능하나 //매개변수가 많을때는 생산적이지 못함 a = fin_diff([]double x) {return sin(..
3.8 펑터 펑터(Functor), 함수 개체(Functional Object) 함수처럼 호출할수 있는 연산자를 제공하는 클래스 //함수포인터를 사용한 유한 차분 double fin_diff(double f(double), double x, double h) { return (f(x + h) - f(x)) / h; } double sin_plus_cos(double x) { return sin(x) + cos(x); } int main() { cout
3.7 타입이 아닌 템플릿 매개변수 값도 템플릿 인자가 될 수 있다. 정수, bool, 토인터 타입만 가능 template class fsize_vector { using self = fsize_vector; public: using value_type= T; const static int my_size = Size; fsize_vector(int s= Size) { assert(s == Size); } self& operator=(const self& that) { std::copy(that.data, that.data + Size, data); return *this; } self operator+(const self& that) const { self sum; for (int i= 0; i < my..
템플릿 특수화 템플릿은 많은 인수타입에 대해 동일한 구현을 사용할수 있다. 그러나 일부 타입에 대해서는 다른동작을 구현해야 할때도 있다. 이를 위해 템플릿 특수화(Template Speicalization)을 사용하자. 하나의 타입에 대한 특수화 벡터 클래스에서 bool타입에 대해 특수화 bool값을 1바이트로 패킹하여 메모리 절약을 해보자. template class vector { public: explicit vector(int size) : my_size(size), data(new unsigned char[(my_size+7) / 8]) {} vector() : my_size(0) {} //상수 접근 연산자 bool operator[](int i) const { return (data[i/8] ..
3.4 타입 추론과 정의 auto 변수 타입 auto타입은 모든 표현식에 적용되는 자동타입이 아닌 한번 정해진 뒤에는 변하지 않는 타입 auto i = 2 * 7.5, j = std::sqrt(3.7); //정상: double auto i - 2 * 4, j = std::sqrt(3.7); //오류: i=int j=double auto i = 2 * 4, j; //오류: j가 초기화되지 않음 auto v = g(x, y, z); //g의 결과 타입 auto& ri = i; //i에 대한 레퍼런스 const auto& cri = i; //i에 대한 const 레퍼런스 auto&& ur = g(x, y, z); //g결과에 대한 포워드 레퍼런스 표현식의 타입 (C++11) decltype은 표현식의 타입을 ..
3.3 클래스 템플릿 컨테이너 예제 템플릿을 사용하여 제네릭 클래스를 만들어보자 template class vector { public: explicit vector(int size) //암시적 변환을 막음 explicit : my_size(size), data( new T[my_size] ) {} vector() : my_size(0), data(0) {} vector(const vector& that) : my_size(that.my_size), data(new T[my_size]) { std::copy(&that.data[0], &that.data[that.my_size], &data[0]); } int size() const { return my_size; } const T& operator[](..
3.2 네임스페이스와 함수 룩업 네임스페이스 struct global {}; namespace c1 { struct c1c{}; namespace c2 { struct c2c {}; struct cc { global x; c1c y; c2c z; } } } struct same {}; //#1 namespace c1 { struct same {}; //#2 namespace c2 { struct same {}; //#3 struct csame { ::same x; //#1 c1::same y; //#2 same z; //#3 } } } struct same {}; //#1 namespace c1 //#a { struct same {}; //#2 namespace c2 { struct same {}; //..
제네릭 프로그래밍 함수 템플릿 함수 템플릿(Function Template)은 잠재적으로 무한한 함수 오버로드를 생성하는 청사진 int max(int a, int b) { return a > b ? a : b; } int max(double a, double b) { return a > b ? a : b; } //위 두개의 함수를 템플릿을 사용하면 아래와 같이 한번만 구현하면 된다 template T max(T a, T b) { return a > b ? a : b; } //다음 함수는 각 리터럴에 의해 각 타입이 인스턴스화 된다 cout
연산자 오버로딩 디자인 일관성있게 디자인하자 도메인 특정 임베디드 언어(Domain-Specific Embedded Language) DSEL 특정 영역의 해결이나 표현을 위해 그 영역에 맞는 특화된 도구를 사용하자는 의미인 듯 우선순위를 존중하자 오버로드한 연산자의 의미와 의도한 우선순위가 C++의 우선순위와 일치하도록 하자 A = B ^ 2 + C; // B제곱에 C를 더하고 싶었겠지만 A = B ^ (2 + C); //컴파일러에서는 이렇게 이해한다 멤버함수 또는 자유 함수 std::cout
2.6 멤버 변수에 접근하기 접근 함수 //게터와 세터를 도입하여 변수에 접근 complex c; c.set_r(c.get_r() + 5); class complex { public: double& real() {return r;} } //레퍼런스를 반환하는 함수를 사용 c.real() += 5; //자유함수 선언 inline double& real(complex& c) { return c.real(); } 첨자 연산자 class vector { public: double at(int i) { assert(i >= 0 && i = 0 && i < my_size); ret..