3. Effective Modern C++ Study
C++ Korea
template<typename T>
void logAndAdd(T&& name)
{
auto now = std::chrono::system_clock::now();
log(now, “logAndAdd”);
names.emplace(std::forward<T>(name));
}
std::string petName(“Darla”);
logAndAdd(petName);
logAndAdd(“Patty Dog”);
3
4. Effective Modern C++ Study
C++ Korea
std::string nameFromIdx(int idx);
void logAndAdd(int idx)
{
auto now = std::chrono::system_clock::now();
log(now, “logAndAdd”);
names.emplace(nameFromIdx(idx));
}
logAndAdd(22);
short nameIdx;
logAndAdd(nameIdx); // 오류!
4
6. Effective Modern C++ Study
C++ Korea
template<typename T>
void logAndAddName(T&& name) { … }
void logAndAddNameIdx(int idx) { … }
6
7. Effective Modern C++ Study
C++ Korea
class Person {
public:
template<typename T>
explicit Person(T&& n)
: name(std::forward<T>(n)) { }
explicit Person(int idx)
: name(nameFromIdx(idx)) { }
};
7
8. Effective Modern C++ Study
C++ Korea
template<typename T>
void logAndAdd(const T& name) { … }
8
9. Effective Modern C++ Study
C++ Korea
class Person {
public:
explicit Person(std::string n)
: name(std::move(n)) { }
explicit Person(int idx)
: name(nameFromIdx(idx)) { }
};
9
13. Effective Modern C++ Study
C++ Korea
template<typename T>
void logAndAdd(T&& name) {
logAndAddImpl(std::forward<T>(name), std::is_integral<T>());
}
13
14. Effective Modern C++ Study
C++ Korea
template<typename T>
void logAndAdd(T&& name) {
logAndAddImpl(std::forward<T>(name),
std::is_integral<typename std::remove_reference<T>::type>();
}
std::is_integral<std::remove_reference_t<T>>();
14
15. Effective Modern C++ Study
C++ Korea
template<typename T>
void logAndAddImpl(T&& name, std::false_type)
{
auto now = std::chrono::system_cloc::now();
log(now, “logAndAdd”);
names.emplace(std::forward<T>(name));
}
void logAndAddImpl(int idx, std::true_type)
{
logAndAdd(nameFromIdx(idx));
}
런타임 값
컴파일 타임 값
15
18. Effective Modern C++ Study
C++ Korea
class Person {
public:
template<typename T,
typename = typename std::enable_if<condition>::type>
explicit Person(T&& n);
}
http://en.cppreference.com/w/cpp/language/sfinae
18
19. Effective Modern C++ Study
C++ Korea
template<typename T>
T const& max(T const& a, T const& b) {
return a < b ? b : a;
}
template<typename T1, typename T2>
T1 const& max(T1 const& a, T2 const& b) {
return a < b ? b : a;
}
int g = max(1, 1.0);
타입 추론
(T = int, double)
→ 추론 과정 실패
타입 추론
(T1 = int, T2 = double)
→ 추론 성공
19
23. Effective Modern C++ Study
C++ Korea
class Person {
public:
template<
typename T,
typename = typename std::enable_if<
!std::is_same<Person,
typename std::decay<T>::type
>::value
>::type
>
explicit Person(T&& n);
};
23
24. Effective Modern C++ Study
C++ Korea
class SpecialPerson : public Person {
public:
SpecialPerson(const SpecialPerson& rhs)
: Person(rhs) { … }
SpecialPerson(SpecialPerson&& rhs)
: Person(std::move(rhs)) { … }
};
24
27. Effective Modern C++ Study
C++ Korea
class Person {
public:
template<
typename T,
typename = typename std::enable_if<
!std::is_base_of<Person,
typename std::decay<T>::type
>::value
>::type
>
explicit Person(T&& n);
};
27
28. Effective Modern C++ Study
C++ Korea
class Person {
public:
template<
typename T,
typename = std::enable_if_t<
!std::is_base_of<Person, std::decay_t<T>>::value
>
>
explicit Person(T&& n);
};
28
29. Effective Modern C++ Study
C++ Korea
class Person {
public:
template<
typename T,
typename = std::enable_if_t<
!std::is_base_of<Person, std::decay_t<T>>::value
&&
!std::is_integral<std::remove_reference_T<T>>::value
>
>
explicit Person(T&& n) : name(std::forward<T>(n)) { … }
explicit Person(int idx) : name(nameFromIdx(idx)) { … }
};
29
33. Effective Modern C++ Study
C++ Korea
static_assert(
std::is_constructible<std::string, T>::value,
“Parameter n can’t be used to construct a std::string”
);
33
50. Effective Modern C++ Study
C++ Korea
template<typename T>
void fwd(T&& param)
{
f(std::forward<T>(param));
}
template<typename… Ts>
void fwd(Ts&&… params)
{
f(std::forward<Ts>(params)…);
}
가변 템플릿 사용
f(expression);
fwd(expression);
50
51. Effective Modern C++ Study
C++ Korea
void f(const std::vector<int>& v);
f({1, 2, 3}); // “{1, 2, 3}”은 암시적으로 std::vector<int>로 변환됨
fwd({1, 2, 3}); // 오류! 컴파일이 되지 않음
51
56. Effective Modern C++ Study
C++ Korea
class Widget {
public:
static const std::size_t MinVals = 28; // MinVals 선언
};
// MinVals 정의 없음
std::vector<int> widgetData;
widgetData.reserve(Widget::MinVals); // MinVals 사용
56
57. Effective Modern C++ Study
C++ Korea
void f(std::size_t val);
f(Widget::MinVals); // “f(28)”처럼 취급됨
fwd(Widget::MinVals); // 오류! 링크가 되지 않음
57
58. Effective Modern C++ Study
C++ Korea
const std::size_t Widget::MinVals; // Widget의 .cpp 파일에서
58
59. Effective Modern C++ Study
C++ Korea
void f(int (*pf)(int)); // pf = “Processing Function(처리 함수)”
void f(int pf(int)); // 위에 있는 f와 같음
int processVal(int value);
int processVal(int value, int property);
59
60. Effective Modern C++ Study
C++ Korea
f(processVal); // 정상 실행
fwd(processVal); // 오류! 어떤 processVal?
60
61. Effective Modern C++ Study
C++ Korea
template<typename T>
T workOnVal(T param) // 값을 처리하는 템플릿
{ … }
fwd(workOnVal); // 오류! 어떤 workOnval을 인스턴스화?
61
62. Effective Modern C++ Study
C++ Korea
using ProcessFuncType = int (*)(int);
ProcessFuncType processValPtr = processVal;
fwd(processValPtr); // 정상 실행
fwd(static_cast<ProcessFuncType>(workOnVal)); // 정상 실행
62
63. Effective Modern C++ Study
C++ Korea
struct IPv4Header {
std::uint32_t version:4,
IHL:4,
DSCP:6,
ECN:2,
totalLength:16;
};
void f(std::size_t sz);
IPv4Header h;
63
64. Effective Modern C++ Study
C++ Korea
f(h.totalLength); // 정상 실행
fwd(h.totalLength); // 오류!
64
65. Effective Modern C++ Study
C++ Korea
// 비트 필드 값의 복사본
auto length = static_cast<std::uint16_t>(h.totalLength);
fwd(length); // 복사본을 포워드
65