컴파일러가 주어진 조건(표현식)을 가지고 타입을 결정하는 과정
__FUNCTION__: C++ 표준, 함수 이름만 나타냄
__PRETTY_FUNCTION__: 인자와 반환 값을 나타냄 (g++, clang++)
__FUNCSIG__: 인자와 반환 값을 나타냄 (Visual Studio, cl.exe)
Template Type Deduction에서 알아야 하는 것
T arg: 인자를 값으로 받을 때
T& arg: 인자를 lvalue reference로 받을 때
T&& arg: 인자를 rvalue reference로 받을 때
인자로 배열이 전달 될 때
T를 값으로 받을 때
template<typename T> void foo(T arg)
{
while (--arg > 0 ) {}
}
int main()
{
int n = 10;
int& r = n;
const int c = 10;
const int& cr = c;
foo(n); // T=int
foo(r); // T=int
foo(c); // T=int
foo(cr);// T=int
}
int main()
{
const char* const s = "hello";
// s는 상수 포인터이므로 포인터의 const 속성이 제거
foo(s); // T=const char*
}
template<typename T> void foo(T& arg)
{
}
int main()
{
int n = 10;
int& r = n;
const int c = 10;
const int& cr = c;
foo(n); // T=int arg=int&
foo(r); // T=int arg=int&
foo(c); // T=const int arg=const int& // 상수 객체는 상수 참조로만 가리킬 수 있음
foo(cr);// T=const int arg=const int&
}
규칙 2
Template 인자를 lvalue reference(T& arg)로 받을 때
T의 타입과 arg의 타입은 다름
함수 인자의 reference를 제거하고 T의 타입을 결정
인자가 가진 const, volatile 속성은 유지
T를 배열로 받을 때
template<typename T> void foo(T arg) // T arg = x
{
//int arg[3] = x; // 이렇게 추론되면 컴파일 에러이므로
//int* arg = x; // T를 포인터로 추론
}
template<typename T> void goo(T& arg)// T& arg = x
{
//int(&arg)[3] = x; // 배열을 가리키는 참조, arg가 x를 가리킴
}
int main()
{
int x[3] = {1,2,3};
foo(x);
goo(x);
}
template<typename T> void foo(T s1, T s2)
{
// T가 char*로 바껴서 같은 타입
}
template<typename T> void goo(T& s1, T& s2)
{
// T가 const char[7], const char[6]로 서로 달라 컴파일 에러
}
int main()
{
foo("orange", "apple"); // ok
// foo(const char[7], const char[6])
// goo("orange", "apple"); // error
// goo(const char[7], const char[6])
goo("orange", "banana"); // 글자의 개수가 같아 컴파일 성공
}
template: 함수 인자로 타입 추론 (T arg = 함수인자;)
auto: 우변의 표현식으로 타입 추론 (auto a = 표현식;)
템플릿 규칙과 동일
int main()
{
int n = 10;
int& r = n;
const int c = 10;
const int& cr = c;
// 규칙 1.
auto a1 = n; // auto=int
auto a2 = r; // auto=int
auto a3 = c; // auto=int
auto a4 = cr;// auto=int
// 규칙 2.
auto& a5 = n; // auto=int a5=int&
auto& a6 = r; // auto=int a6=int&
auto& a7 = c; // auto=const int a7=const int&
auto& a8 = cr;// auto=const int a8=const int&
int x[3] = {1,2,3};
auto a = x; // auto=int*
auto& b = x; // auto=int[3] b = int(&)[3]
}
int main()
{
auto a1 = 1; // int
auto a2 = {1}; // std:initializer_list<int>
auto a3{1}; // int
std::vector<int> v1(10,0);
std::vector<bool> v2(10,false); // bool(1byte)을 10개를 보관하지 않고 10bit 보관
auto a4 = v1[0]; // int
auto a5 = v2[0]; // proxy객체 (bool이 아님!)
}