1. std::function
<funcional> 헤더에 정의된 타입.
함수 포인터, 함수 객체, 람다 표현식등 호출이 가능한 것이라면 저장이 가능하다.
템플릿으로 정의되어 있는데, 이에 대한 템플릿 파라미터는 함수 원형에 대한 정의를 받는다.
std::function<R(ArgTypes...)>
R은 리턴 타입, ArgTypes는 쉼표로 분리된 함수의 인자 타입 목록
ex) std::function을 함수 포인터 변수로 사용하는 방법
void func(int num, const string& str)
{
cout << "func(" << num << ", " << str << ")" << endl;
}
int main()
{
function<void(int, const string&)> f1 = func; // C++11 에서는 auto f1 = func;
f1(1, "test");
return 0;
}
ex) std::function 타입 변수를 콜백으로 사용하는 방법
bool isEven(int num)
{
return num % 2 == 0;
}
int main()
{
vector<int> vec;
for (int i=0; i<10; i++) {
vec.push_back(i);
}
auto f2 = isEven; // function<bool(int)> 타입
int cnt = count_if(vec.cbegin(), vec.cend(), f2);
cout << cnt << "even numbers" << endl;
return 0;
}
ex) 함수 포인터를 파라미터로 받는 방법
void process(const vector<int>& vec, function<void(int)> f)
{
for (auto& i : vec) {
f(i);
}
}
void print(int num)
{
cout << num << "";
}
int main()
{
vector<int> vec;
for (int i=0; i<10; i++) {
vec.push_back(i);
}
process(vec, print);
cout << endl;
int sum = 0;
process(vec, [&sum](int num) { sum += num; });
cout << "sum = " << sum << endl;
return 0;
}
2. 분수
<ratio> 헤더에 정의.
C++11은 분수 라이브러리를 제공하여 유한 유리수를 컴파일 타임에 연산할 수 있도록 한다.
분수를 표현하기 위한 분자와 분모는 std::intmax_t 타입의 컴파일 타임 상수로 표현한다.
유리 값을 나타내는 ratio 객체는 다음처럼 typedef를 이용하여 정의해야 한다.
typedef ratio<1, 60> r1;
유리수 r1의 분자와 분모는 컴파일 타임 상수이다. 다음과 같이 접근 할 수 있다.
intmax_t num = r1::num;
intmax_t den = r1::den;
ratio 객체는 컴파일 타임 상수이기 떄문에 분자와 분모도 컴파일 타임에 확정되어 있어야 한다.
const intmax_t n = 1;
const intmax_t d = 60;
typedef ratio<n, d> r1;
유리수가 컴파일 타임 상수로 표현되기 때문에, 일반적인 표준 산술 연산자를 사용할 수 없고, 특별한 템플릿을 조합하여 사용하여야 한다.
ratio_add
ratio_substract
ratio_multiply
ratio_divide
다음의 코드는 1/30, 1/60을 나타내는 두 개의 ratio를 정의한 다음, ratio_add 템플릿을 이용해 두 유리수를 더하고 그 약분된 결과 1/20을 가지는 타입 result를 정의한다.
typedef ratio<1, 60> r1;
typedef ratio<1, 30> r2;
typedef ratio_add<r1, r2>::type result;
3. 크로노 라이브러리
<chrono> 헤더에 정의. (네임스페이스 std::chrono)
시간/날짜 관련 연산을 위한 라이브러리.
3.1 시간 간격 계산을 위한 duration 클래스
시간 Tick의 개수와 틱의 주기를 저장한다.
template <class Rep, class Period = ratio<1>> class duration {...}
ex) 틱 주기가 1초
duration<long> d1;
ex) 틱 주기가 10초
duration<long, ratio<60>> d2;
ex) 틱 주기가 1/60초
duration<double, ratio<1,60>> d3;
ex) 틱 주기가 1/1000000초
duration<long long, milli> d4;
3.2 시계 조작을 위한 clock 클래스
기준 시간으로부터 상대 시간을 저장하는 time_point와, duration으로 구성
system_clock : 시스템 수준의 실시간 값.
steady_clock : 내장 time_point가 절대 뒤로 돌려지지 않음을 보장.
high_resolution_clock : 정밀도 높은 시간 측정을 위해 최소 틱 주기를 가짐.
std::chrono::system_clock::time_point tpoint = std::chrono::system_clock::now();
time_t tt = std::chrono::system_clock::to_time_t(tpoint);
struct tm t;
localtime_s(&t, &tt);
std::cout << std::put_time(&t, "%H:%M:%S") << std::endl; // 또는 <time.h>의 strftime() 함수
ex) 특정 코드의 수행시간을 측정
auto start = std::chrono::system_clock::now();
double d = 0;
for (int i = 0; i < 1000000; i++) {
d += sqrt(sin(i) * cos(i));
}
auto end = std::chrono::system_clock::now();
auto diff = end - start;
std::cout << std::chrono::duration<double, std::milli>(diff).count() << "ms" << std::endl;
3.3 time_point 클래스
특정 시점을 표현하고, 기준 시간으로부터 상대 시간으로 duration에 저장된다.
ex) 리눅스/유닉스는 1970-01-01이 기준시간이 되어 1초 단위로 기록
ex)
std::chrono::time_point<std::chrono::steady_clock> tp1;
// time_point에 10분을 더한다.
tp1 += std::chrono::minutes(10);
// 에포치 시간과 time_point의 시간차를 duration으로 저장한다.
auto d1 = tp1.time_since_epoch();
// duration을 초 단위로 변환하고 콘솔에 출력한다.
std::chrono::duration<double> d2(d1);
std::cout << d2.count() << " seconds" << std::endl;
4. 난수 생성
4.1 random_device
소프트웨어적이 아닌 특별한 하드웨어를 통해 난수를 생성.
사용 가능한 난수 발생 장치가 없으면 소프트 웨어 알고리즘으로 대체 가능.
ex)
std::random_device rnd;
std::cout << "Entropy: " << rnd.entropy() << std::endl;
std::cout << "Min value: " << rnd.min() << ", Max value: " << rnd.max() << std::endl;
std::cout << "Random number: " << rnd() << std::endl;
4.2 linear_congruential_engine
선형 합동 난수 생성엔진은 최소 메모리 사용량을 가짐.
난수 상태 정보는 마지막으로 생성된 난수 또는 난수 씨앗을 나타내는 정수밖에 없다.
난수 주기는 알고리즘에 사용된 파라미터에 의존적이고, 최대 2^64까지 가능하다.
4.3 Mersenne_twister_engine
메르센 트위스터 난수 엔진은 소프트웨어로된 의사 난수 생성기 중에서 가장 좋은 품질의 난수를 생성한다.
난수 주기가 알고리즘의 파라미터에 따라 다르긴 하지만 선형 합동 난수 엔진보다 훨씬 길다.
4.4 subtract_carry_engine
감산 캐리(자리 내림) 난수 엔진은 상태 저장을 위해 100byte(25개 정수)정도의 메모리를 필요로 한다.
메르센 트위스터 엔진보다 난수의 품질은 떨어진다.
'프로그래밍 > C,C++' 카테고리의 다른 글
C++ 연산자 오버로딩 (0) | 2018.04.25 |
---|---|
STL 커스터마이징 (0) | 2018.04.18 |
문자열과 정규 표현식 (0) | 2018.04.15 |
함수 객체 (0) | 2018.04.15 |
람다(lambda) (0) | 2018.04.11 |