예시코드)
https://github.com/GbLeem/CPP_Study/tree/main/NoCode
43.cpp ~ 47.cpp
#include<algorithm>
#include<iostream>
#include<vector>
template<typename T>
T add(T a, T b)
{
return a + b;
}
int main()
{
//STL 예시1
int maxI = std::max<int>(1, 5);
float maxF = std::max<float>(1.2f, 2.5f);
std::cout << maxI << std::endl;
std::cout << maxF << std::endl;
//STL 예시2
std::vector<int> vecI;
std::vector<float> vecF;
//직접 만든 template 함수 예시
int resI = add<int>(1, 2);
auto res = add(1.2, 2.2); //type deduction
}
#include<iostream>
int main()
{
auto a = 1;
std::cout << typeid(a).name() << std::endl; //int
auto b = 1.1;
std::cout << typeid(b).name() << std::endl; //double
auto c = "ABC";
std::cout << typeid(c).name() << std::endl; //const char*
}
printVar<int>(1.2);
의 경우 int, 1이 출력template<typename T>
void printVar(T a)
{
std::cout << typeid(a).name() << std::endl;
std::cout << a << std::endl;
}
int main()
{
int a = 1;
printVar<int>(a); //int, 1출력
printVar(a); //int, 1출력 -> deduction
}
#include<iostream>
template<typename T>
void printVar(T &&a) //forward reference(=universal reference)
{
std::cout << typeid(a).name() << std::endl;
std::cout << a << std::endl;
}
int main()
{
int a = 1;
//printVar<int>(a); 컴파일 에러!!
printVar(a); //컴파일 에러 발생 X
//-> T는 int&, function argument는 int&
printVar(std::move(a));
//-> T는 int, function argument는 int&&
return 0;
}
#include<iostream>
#include<string>
template<typename T>
void printVar(T &&a)
{
std::cout << a << std::endl;
}
int main()
{
int a = "good";
printVar(a); //good 출력
printVar(std::move(a)); //good 출력
return 0;
}
#include<iostream>
#include<string>
template<typename T>
void printVar(T &&a)
{
std::string localVar{std::move(a)};
//std::string localVar{std::forward<T>(a)};
//-> std::forward를 사용한 경우 두 경우 모두 good 출력
std::cout << localVar << std::endl;
}
int main()
{
int a = "good";
//T는 string&, function argument는 string&
printVar(a); // good 출력
//T는 string&&, function argument는 string
printVar(std::move(a)); // 아무것도 출력 안된다
//std::forward() 사용 시 출력 결과
printVar(a); // good 출력
printVar(std::move(a)); // good 출력
std::cout<< a << std::endl; // 아무것도 출력 안된다.
return 0;
}
#include<iostream>
//multiple type parameter -> 두개 이상의 typename
template<typename IT, typename T>
IT foo1(IT first, IT last, const T& value)
{
while (first != last)
{
if (*first == value)
{
return first;
}
first++;
}
return last;
}
//non type parameter-> typename 이외의 일반 타입 함께 쓰기
template<typename T, std::size_t N>
T foo2(T a)
{
return N * a;
}
//parameter pack -> 갯수를 지정 안함
template<typename ...T>
void foo3(T && ... args)
{
(std::cout << ... << args) << std::endl;
}
int main()
{
//non type 예시
std::cout << foo2<double, 4>(2.0) << std::endl;
//parameter pack 예시
foo3(1, 2, 3);
foo3("ABC", "good");
return 0;
}
template<typename T>
T foo(T a);
template<typename T>
T foo(T a)
{
return a * 2;
}
template int foo<int>(int); //type explicit instantiation
#include <iostream>
#include "foo.h"
int main()
{
std::cout << foo<int>(1) << std::endl;
//std::cout << foo<double>(1.0) << std::endl; 컴파일 에러!
//-> int에 대한 type explicit instantiation만 했기 때문에
return 0;
}
std::vector<int> vecInt;
std::vector<Widget> vecWidget;
using myType = std::vector<std::array<uint8_t,64>>;
#include<iostream>
#include<vector>
template<typename T>
using myKey = std::vector<std::array<T, 64>>
int main()
{
using myInt = int;
myInt a{ 10 };
std::cout << a << std::endl;
//Aliasing template 예시
myKey<int> intKeys;
myKey<double> doubleKeys;
return 0;
}
pi_v
라는 variable template가 만들어져 있다.#include<iostream>
template<class T>
constexpr T pi = T(3.1415926535897932385L);
int main()
{
int intPi = pi<int>;
float floatPi = pi<float>;
return 0;
}
#include<iostream>
#include<string>
template<typename T>
T sum(T a, T b)
{
return a + b;
}
int main()
{
//아래 두개의 코드 모두 컴파일이 제대로 된다.
//그러나 프로그래머는 sum은 int만 되도록 만들고 싶을때
//-> template concept 사용 (컴파일 에러를 발생시켜준다)
std::cout << sum<int>(10,10) << std::endl;
std::cout << sum<std::string>("abc", "def") <<std::endl;
}
#include<iostream>
#include<string>
#include<concepts>
//std::integral이용
template<typename T>
T sum1(T a, T b)
{
static_assert(std::integral<T>, "only integral types");
return a + b;
}
//requires 이용
template<typename T>
T sum2(T a, T b) requires std::integral<T>
{
return a + b;
}
int main()
{
std::cout << sum1<int>(10, 10) << std::endl; //ok
//std::cout << sum1<std::string>("abc", "def") << std::endl; 컴파일 에러
std::cout << sum2<int>(10, 10) << std::endl; //ok
//std::cout << sum2<std::string>("abc", "def") << std::endl; 컴파일 에러
return 0;
}
//사용자 지정 concept -> int와 float까지 가능하게 해준다.
template<typename T>
concept Summable = std::integral<T> || std::floating_point<T>;
//사용자 지정 concept 반영 템플릿
template<typename T>
T sum(T a, T b) requires Summable<T>
{
return a + b;
}
//operator를 통한 concept 지정 -> - 연산이 없는 경우 컴파일 에러 발생시킴 (ex: string)
template<typename T>
concept Addable = requires(T x)
{
x + x;
x - x;
};