프로그래밍/C,C++

유틸리티 라이브러리

MAKGA 2018. 4. 18. 20:18
320x100

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개 정수)정도의 메모리를 필요로 한다.

메르센 트위스터 엔진보다 난수의 품질은 떨어진다.

320x100

'프로그래밍 > 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