C++17 표준 라이브러리에 새로 추가된 알고리즘과 기타 변경 사항 소개
C++17 표준 라이브러리 소개 시리즈의 마지막 글. 새로 추가된 알고리즘과 기타 변경 사항을 소개합니다.
"핵심 C++ 표준 라이브러리" 부록 A 방출 계획의 마지막 글입니다. C++에 새로 추가된 알고리즘들과 자잘한 변경 사항을 간략하게 정리했습니다.
새로 추가된 알고리즘
C++17에서 새로 추가된 알고리즘들을 간략하게만 소개하겠다. 이들은 모두 std
이름공간에 속한다.
for_each_n
:for_each
와 같되[first, last)
가 아니라[first, first+n)
을 입력 범위로 사용하며,first+n
을 돌려준다(참고로for_each
의 직렬 버전은 사용자 지정 함수를 돌려주고 병렬 버전은 아무것도 돌려주지 않는다). 필요한 헤더는<algorithm>
이며, 병렬 버전도 있다.sample
: 주어진 범위의 요소 n개를 주어진 확률 분포에 따라 무작위로 선택한다. 필요한 헤더는<algorithm>
이다.uninitialized_move
와uninitialized_move_n
: 주어진 요소들을 초기화되지 않은 메모리 영역으로 이동한다. 필요한 헤더는<memory>
이며, 병렬 버전도 있다.clamp
: 주어진 값이 하한보다 작으면 하한을, 상한보다 크면 상한을 돌려준다. 그 외에는 주어진 값을 돌려준다. 비교 함수를 지정할 수 있다. 필요한 헤더는<algorithm>
이다.reduce
: 분산 처리나 병렬 처리 관련 프레임워크 또는 언어에서 흔히 볼 수 있는 Map-Reduce(사상-축약) 패턴의 Reduce 단계에 해당하는 알고리즘이다. 필요한 헤더는<numeric>
이며, 병렬 버전도 있다. 참고로 Map에 해당하는 표준 라이브러리 알고리즘은transform
이다. 기존accumulate
알고리즘에 병렬 버전이 추가되지 않았는데, 대신reduce
의 병렬 버전을 사용하면 된다.transform_reduce
: Map-Reduce에 해당하는 알고리즘으로, 요소들을 먼저 변환한 후에 축약한다. 필요한 헤더는<numeric>
이며, 병렬 버전도 있다. 기존inner_product
알고리즘에 병렬 버전이 추가되지 않았는데, 대신 이transform_reduce
의 병렬 버전을 사용하면 된다.inclusive_scan
과exclusive_scan:
요소들의 구간 합(prefix sum; 또는 부분합)들을 구한다.inclusive_scan
은 i번째 요소를 i번째 부분합에 포함하고,exclusive_scan
은 포함하지 않는다. 예를 들어 덧셈과 초기치 0을 사용한다고 할 때 {1, 1, 0, 2, 3}의inclusive_scan
결과는 {1, 2, 2, 4, 7}이고exclusive_scan
결과는 {0, 1, 2, 2, 4}이다. 덧셈 이외의 합산 함수를 지정할 수 있으며, 부분합의 초기치도 다르게 지정할 수 있다(기본은 0). 필요한 헤더는<numeric>
이며, 병렬 버전도 있다. 기존partial_sum
알고리즘에 병렬 버전이 추가되지 않았는데, 대신inclusive_scan
의 병렬 버전을 사용하면 된다.transform_inclusive_scan
과transform_inclusive_scan:
요소들을 먼저 변환한 후 구간 합을 구한다. 필요한 헤더는<numeric>
이며, 병렬 버전도 있다.
기타 변경 사항
그 외에 C++17 표준 라이브러리의 변경 사항을 정리하자면 다음과 같다.
random_shuffle
,auto_ptr
,result_of
,bind1st
,unxepected
등 이전 표준들이 폐기 예정으로 분류한 구성요소들이 실제로 폐기되었다(표 A.3).- 활성 예외 객체 검출 함수
uncaught_exception
이 폐기 예정으로 분류되고, 이를 대신하는uncaught_exceptions
가 추가되었다. 전자는 현재 스레드에 활성 예외 객체(던져졌지만 아직 해당catch
절에 도달하지 않은 예외 객체)가 있는지의 여부(bool
)를 돌려주지만, 후자는 현재 스레드의 활성 예외 객체 개수(int
)를 돌려준다(<exception>
헤더). map
과unordered_map
에try_emplace
와insert_or_assign
이라는 새로운 멤버 함수가 추가되었다. 이들은 주어진 키가 컨테이너에 없는 경우에만 새 요소를 생성 또는 삽입한다.- 컨테이너 멤버 함수
size
,empty
,data
의 비멤버 함수 버전인std::size
,std::empty
,std::data
가 추가되었다(<iterator>
헤더). - 메모리를 구성하는 바이트byte의 개념을 좀 더 명시적으로 표현하기 위해
std::byte
라는 형식이 추가되었다. 내부적으로std::byte
는 하나의 열거형 클래스(enum class
)인데, 바탕 자료 형식은unsigned char
이다.unsigned char
와는 달리std::byte
는 문자 형식으로도, 수치(산술) 형식으로도 간주되지 않는다. 개념적으로std::byte
는 단지 비트들의 집합일 뿐이며, 산술 연산자들은 지원하지 않고 비트별 논리 연산자들과 자리이동(shift) 연산자들만 지원한다. 임의의 정수 n을 std::byte 객체로 변환하려면std::byte{n}
형태의 표현식을 사용하고(C++17부터는 이런 식으로 열거형 객체를 생성할 수 있게 되었다), 그 반대의 변환은std::to_integer
함수(역시 C++17에서 추가되었다)를 사용하면 된다. - 컴파일 시점에서 형식 특질들의 논리합, 논리곱, 부정을 산출하는 메타 함수
conjunction
,disjunction
,negation
이 추가되었으며,is_aggregate
,is_invocable
,is_swappable
등 다양한 컴파일 시점 형식 판정 함수가 추가되었다(<type_traits>
헤더). - 최대공약수와 최소공배수를 돌려주는 수학 함수
gcd
와lcm
이 추가되었으며(<numeric>
헤더), 타원적분, 베셀 함수, 르장드르 함수, 노이만 함수, 리만 제타 함수 등 다양한 특수 함수가 추가되었다(<cmath>
헤더). 표 A.4에 특수 함수들이 나열되어 있다.
표 A.3 폐기된 구성요소들
auto_ptr
, const_mem_fun_t
, pointer_to_binary_function
,
binary_function
, get_unexpected
, pointer_to_unary_function
,
bind1st
, mem_fun1_ref_t
, ptr_fun
,
bind2nd
, mem_fun1_t
, random_shuffle
,
binder1st
, mem_fun_ref_t
, set_unexpected
,
binder2nd
, mem_fun_ref
, unary_function
,
const_mem_fun1_ref_t
, mem_fun_t
, unexpected
,
const_mem_fun1_t
, mem_fun
, unexpected_handler
,
const_mem_fun_ref_t
표 A.4 특수 수학 함수
assoc_laguerre
, comp_ellint_3f
, ellint_1l
, legendre
,
assoc_laguerref
, comp_ellint_3l
, ellint_2
, legendref
,
assoc_laguerrel
, cyl_bessel_i
, ellint_2f
, legendrel
,
assoc_legendre
, cyl_bessel_if
, ellint_2l
, riemann_zeta
,
assoc_legendref
, cyl_bessel_il
, ellint_3
, riemann_zetaf
,
assoc_legendrel
, cyl_bessel_j
, ellint_3f
, riemann_zetal
,
beta
, cyl_bessel_jf
, ellint_3l
, sph_bessel
,
betaf
, cyl_bessel_jl
, expint
, sph_besself
,
betal
, cyl_bessel_k
, expintf
, sph_bessell
,
comp_ellint_1
, cyl_bessel_kf
, expintl
, sph_legendre
,
comp_ellint_1f
, cyl_bessel_kl
, hermite
, sph_legendref
,
comp_ellint_1l
, cyl_neumann
, hermitef
, sph_legendrel
,
comp_ellint_2
, cyl_neumannf
, hermitel
, sph_neumann
,
comp_ellint_2f
, cyl_neumannl
, laguerre
, sph_neumannf
,
comp_ellint_2l
, ellint_1
, laguerref
, sph_neumannl
,
comp_ellint_3
, ellint_1f
, laguerrel