6. decltype (C++ 11)
int x = 3;
decltype(x) y = x; // y: int
struct A { double x; };
const A* a = new A(0);
decltype(a->x) x3; // x3: double
decltype((a->x)) x4; // x4: const double&
7. auto 반환 (C++ 11)
• C++11부터 auto 타입 변환으로 후행 반환 형식을 제공
• decltype이 유연하게 auto 반환을 사용할 수 있음.
8. auto 반환 (C++ 11)
auto add_function(int a, int b) -> int {
return a+b;
}
template <typename Tbuilder>
auto MakeAndProcessObject(const Tbuilder& b)
-> decltype(builder.makeObject()) {
auto val = builder.makeObject();
return val;
}
9. 함수 반환 값에 대한 auto(C++14)
• auto가 함수 반환 타입을 추론할 수 있도록 확장
(더 이상 후행 반환 형식을 사용할 필요 없음)
• auto 반환이 템플릿 타입 추론을 따라가기 때문에
의도하는 타입변환을 위해 decltype(auto) 형식을 사용
10. 함수 반환 값에 대한 auto(C++14)
auto f(); // 함수 f() 선언. 반환 값 타입 불명.
auto f() { return 1; }
// f(): void -> int
auto& f(int& x) { return x*2; }
// f(): int& ->int&
…
auto i = 3; // i: int
auto r = f(i); // r: int&
11. 함수 반환 값에 대한 auto(C++14)
decltype(auto) add_function(int a, int b) {
return a+b;
}
template <typename Tbuilder>
decltype(auto) MakeAndProcessObject(const
Tbuilder& b) {
auto val = builder.makeObject();
return val;
}
12. constexpr (C++ 11~)
• 변수, 함수, 클래스 등을 컴파일 타임에 결정하는 한정자
• 일반화된 상수 표현식(Generalized constant expression)
• 컴파일 시간에 연산을 가져옮으로써 런타임에 불필요한
연산 수행 시간 줄임
• constexpr을 붙이면 컴파일 시간에 ‘가능한’ 상수화 연산
을 진행 (확인은 std::is_literal_type)으로 확인
13. constexpr 변수 (C++ 11~)
constexpr float x = 42.f; // OK
constexpr float y (108.f); // OK
constexpr int i; // error: 초기화 필요
int j = 0;
constexpr int k = j + 1;
// error: 상수 계산이 불가능
14. constexpr 함수 (C++ 11~)
• constexpr을 함수 반환값에 사용
• 가상으로 재정의된 함수 X
• 함수에 constexpr을 붙일 경우 inline을 암시
• C++11에서는 함수 본문에 지역 변수를 둘 수 없고,
하나의 반환 표현식만 와야 함.
C++14에서는 제약 해제.
• 템플릿 메타 프로그래밍의 친구.
15. constexpr 함수 (C++ 11~)
// for C++11
constexpr int factorial(int n)
{
return n < = 1 ? 1 : (n * factorial(n-1));
}
16. constexpr 함수 (C++ 11~)
// for C++14
constexpr int factorial(int n)
{
int result = 0; // local variable
// multiple statements
if (n <=1) result = 1;
else result = n * factorial(n-1);
return result;
}
17. if constexpr (C++ 17)
• 컴파일 타임에 상수표현식의 boolean을 평가
• constexpr의 condition이 true이면 else statements가,
false이면 then statements가 컴파일에서 제외됨.
18. if constexpr (C++ 17)
// int*가 인자로 넘겨지면 else { return t; }가
// 버려짐, pointer가 아니면 return *t가 버려짐.
template <typename T>
auto get_value(T t)
{
if constexpr (std::is_pointer_v<T>)
return *t;
else
return t;
}
19. if constexpr (C++ 17)
// without if constexpr
template <int N1>
constexpr auto sum() {
return N1;
}
template <int N1, int N2, int… Ns>
constexpr auto sum() {
return N1 + sum <N2, Ns…>();
}
20. if constexpr (C++ 17)
// with if constexpr
template <int N, int… Ns>
constexpr auto sum() {
if constepxr (sizeof…(Ns) == 0)
return N;
else
return N + sum<Ns…>();
}
21. lambda (C++ 11)
• lambda 함수 또는 무명 함수라고 부름
• 함수형 프로그래밍 패러다임에서 차용,
lambda는 함수 오브젝트
• 프로그램 중간에 선언이 가능하며, 현재 프로그램의 상
태를 저장할 수 있음
• C++의 표현력을 증가 시켜 줌
• STL의 알고리즘의 활용에 유용
22. lambda (C++ 11)
• 1. 캡쳐 절(lambda-introduction)
[]: 캡쳐 없음
[&]: 모든 외부 변수 by ref
[=]: 모든 외부 변수 by value
• 2. 매개 변수 목록
• 3. 변경 가능 사양
• 4. 예외처리 동일
• 5. 리턴 타입을 결정
• 6. 람다 몸체
23. lambda (C++ 11)
// lambda를 sum에 저장하고 호출
auto sum = [] (int first, int second) {
return first + second;
};
int res = sum(1,2);
// 정의와 동시에 사용
int x = 1, y = 2;
int z = [x, y](int k){return k*(x+y);}(3);
24. lambda (C++ 11)
// find_if 알고리즘 함수에 인자로 전달
list<int> numbers;
numbers.push_back(1);
…
numbers.push_back(99);
auto result = //const list<int>::const_iterator
find_if(numbers.begin(), numbers.end(),
[](int n) { return (n % 2) == 0 }
); //짝수인 첫 iterator 찾음
25. lambda와 closure (C++ 11)
int a = 7, b = 3;
auto closureFunc = [a, b] (int x) {
cout << a*x + b << endl;
};
closureFunc(5); // 7*5+3 = 38 출력
a = 10, b = 20;
closureFunc(5);
// static lexical binding
// 70이 아니라 38 출력
26. generic lambda (C++ 14)
• 기존(C++11까지의) lambda 함수 인자들은 auto 키워드
를 가질 수 없었음.
• C++14부터는 auto 키워드를 사용할 수 있게 됨
27. generic lambda (C++ 14)
// for C++ 11
auto iAdd = [] (int a, int b) -> int
{ return a+b; }
auto fAdd = [] (float a, float b) -> float
{ return a+b; }
// for C++ 14
auto Add = [] (auto a, auto b)
/*-> decltype(a+b)*/ { return a+b; }
28. constexpr lambda (C++ 17)
• 람다식이 constexpr로 선언되거나 캡처되거나,
상수 내에서 각 데이터 멤버의 초기화가 허용되는 경우
상수식에 사용.
29. constexpr lambda (C++ 17)
int y = 32;
auto answer = [y]() constexpr {
int x = 10;
return y + x;
} // answer := 42
constexpr int Increment(int n) {
return [n] { return n + 1; }();
} // Increment(x)는 상수식
30. concepts (C++ 20)
• 템플릿 선언시, 템플릿으로 올 수 있는 타입에 대한
제한을 정의할 수 있음
• 기존에는 템플릿 프로그래밍에선 type_traits를 이용해서
이를 제한적으로 구현 함
• C++ 11부터 도입하려고 논의하였으나 17까지 표준에
들어오지 못함. 20에는 최우선적으로 논의 중.
32. concepts (C++ 20)
template<typename T>
concept bool Addable = requires (T a, T b) {
a + b;
};
template<typename T> requires Addable<T>
bool add(T a, T b) { return a == b };
add(1, 2) // it’s ok, 1+2 is ok
add(“a”, “b”) // error, “a”+”b” is not ok
33. concepts (C++ 20)
// variable concept from the standard library
template<class T, class U>
concept bool Derived = std::is_based_of<U, T>::value;
template<class T, class U> requires Derived
T* upperCast(U* u) { return static_cast<T*>(u); }
class A {}; class B : public A {}; class C;
A* a1 = upperCast<A, B>(new B()); // it’s ok
A* a2 = upperCast<A, C>(new C()); // compiler error.
// concepts Derived doesn’t match
34. concepts (C++ 20)
template<typename T> using Ref = T&;
template<typename T> concept C =
requires {
typename T::inner; // required nested member name
typename S<T>; // required class template specialization
typename Ref<T>; // required alias template substitution
};
35. concepts (C++ 20)
template<typename T> concept C2 =
requires(T x) {
{*x} -> typename T::inner;
// the expression *x must be valid
// AND the type T::inner must be valid
// AND the result of *x must be convertible to T::inner
{x + 1} -> std::Same<int>;
// the expression x + 1 must be valid
// AND std::Same<decltype((x + 1)), int> must be satisfied
// i.e., (x + 1) must be a prvalue of type int
{x * 1} -> T;
// the expression x * 1 must be valid
// AND its result must be convertible to T
};
36. concepts 기타 특징 (C++ 20)
std::list<int> l = {2, 1, 3};
std::sort(l.begin(), l.end());
• 1. 컴파일 분석이 용이해짐
– 에러의 호출 위치를 내부 구현에서 컨셉으로 가져옴
– 예) 랜덤 접근 반복자가 아니라 다른 종류의 반복자를 쓸 경우
37. concepts 기타 특징 (C++ 20)
// Without concepts, current error display
In instantiation of 'void
std::__sort(_RandomAccessIterator,
_RandomAccessIterator, _Compare) [with
_RandomAccessIterator =
std::_List_iterator<int>; _Compare =
__gnu_cxx::__ops::_Iter_less_iter]':
error: no match for 'operator-' (operand types
are 'std::_List_iterator<int>' and
'std::_List_iterator<int>')
std::__lg(__last - __first) * 2,
38. concepts 기타 특징 (C++ 20)
error: cannot call function 'void
std::sort(_RAIter, _RAIter) [with _RAIter =
std::_List_iterator<int>]‘
note: concept 'RandomAccessIterator()' was not
satisfied
39. concepts 기타 특징 (C++ 20)
• 2. 함수 오버로드 선택
– 함수 오버로딩 시 concept에 따라 타입을 선택할 수 있음.
– 만약 둘 이상의 concept를 만족시키는 경우 좀 더 제약이 많은
콘셉트와 연관된 오버로드 선택.
40. concepts 기타 특징 (C++ 20)
• 3. 타입추론
– 변수 선언과 함수 변환 타입을 정할 때,
concept가 사용되어 무제한의 타입 추론을 하는 auto를 대체
auto x1 = f(y); //x1의 타입은 f의 리턴값에 의해 추론
Sortable x2 = f(y); //x2의 타입도 추론되나, Sortable을
만족하는 경우에만 컴파일 됨