6 분 소요

  • (C++11~) tuple이 추가되어 다수의 요소를 관리할 수 있는 데이터 전달용 개체를 좀 더 간편하게 만들 수 있습니다.
  • (C++11~) move()가 추가되어 좌측값을 우측값으로 형변환할 수 있습니다.
  • (C++11~) move_if_noexcept()가 추가되어 nothrow 보증이 되는 경우에만 &&로 형변환할 수 있습니다.
  • (C++11~) forward()가 추가되어 함수가 전달받은 인자를 다른 함수로 완벽하게 전달할 수 있습니다.
  • (C++11~) declval()이 추가되어 참조 타입 표현식으로 변경할 수 있습니다.
  • (C++11~) quick_exit(), _Exit(), at_quick_exit()가 추가되었습니다.
  • (C++11~) va_copy가 추가되었습니다.
  • (C++14~) exchange()가 추가되어 주어진 값을 바꾸는 작업이 간편해 졌습니다. 특히 이동 생성자와 이동 대입 연산자 구현에 활용할 수 있습니다.
  • (C++17~) as_const()가 추가되어 인자const를 좀더 간편하게 붙일 수 있습니다.
  • (C++17~) optional이 추가되어 값이 있을 수도 있고, 없을 수도 있는 데이터를 처리할 수 있어, 미확정 상태, 값을 처리하기 부적절한 상태, 함수 리턴값 성공 여부 처리를 좀더 단순하게 할 수 있습니다.
  • (C++17~) any가 추가되어 타입의 변동 가능성이 있는 데이터를 비교적 안전하게 사용할 수 있습니다.
  • (C++17~) variant가 추가되어 타입이 다른 여러 데이터들을 동일한 메모리 공간에서 쉽게 관리할 수 있습니다.
  • (C++17~) inplace등이 추가되었습니다. 내부 개체를 생성해서 전달하는 것이 아니라, 내부 개체의 생성자 인수들을 전달하면 내부 개체를 직접 생성하라는 의미로 optional, any, variant 생성자에 더미(Dummy) 개체로 사용됩니다.
  • (C++17~) timespec_get(), timespec이 추가되었습니다.
  • (C++20~) 삼중 비교 연산자가 추가되어 !=, >, <=, >=deprecate 되었습니다.
  • (C++20~) cmp_equal(), cmp_not_equal(), cmp_less(), cmp_greater(), cmp_less_equal(), cmp_greater_equal()이 추가되어 음의 정수와 양의 정수를 정상적으로 비교할 수 있습니다.
  • (C++20~) in_range()가 추가되었습니다. 주어진 value가 주어진 type의 값 범위 내에 있는지 검사합니다.
  • (C++20~) source_location이 추가되어 파일명, 줄번호, 칼럼번호, 함수명등의 정보를 제공합니다.
  • (C++20~) 삼중 비교 관련 유틸리티들이 추가되었습니다.
  • (C++20~) 유틸리티의 constexpr 지원이 개선되어 swap()함수도 constexpr 함수로 변경되었습니다.
  • (C++20~) STL 지원 테스트 매크로가 추가되어 C++11부터 추가된 STL 기능을 지원하는지 테스트 할 수 있습니다.

일반 유틸리티

항목 내용 constexpr
swap() 바꿔치기 합니다. (C++20~)
exchange() (C++14~) 주어진 값을 바꾸고 이전값을 리턴합니다. 이동 생성자와 이동 대입 연산자 구현에 활용할 수 있습니다. (C++20~)

간단한 데이터 개체

항목 내용 constexpr
pair firstsecond로 2개의 요소를 관리합니다. make_pair()를 이용하여 pair를 쉽게 생성할 수 있습니다. 생성자에 따라,
(C++11~)
(C++14~)
(C++20~)
tuple (C++11~) 다수의 요소를 관리할 수 있는 데이터 전달용 개체를 손쉽게 만듭니다. 생성자에 따라,
(C++11~)
(C++14~)
(C++20~)
(C++23~)
optional (C++17~) 값이 있을 수도 있고, 없을 수도 있는 데이터를 처리할 수 있어, 미확정 상태, 값을 처리하기 부적절한 상태, 함수 리턴값 성공 여부 처리를 좀더 단순하게 할 수 있습니다. 생성자에 따라,
(C++17~)
(C++20~)
any (C++17~) 타입의 변동 가능성이 있는 데이터를 비교적 안전하게 사용할 수 있습니다. 생성자에 따라,
(C++17~)
variant (C++17~) 타입이 다른 여러 데이터들을 동일한 메모리 공간에서 쉽게 관리할 수 있습니다. (C++17~)

개체 비교

대소 비교의 논리 조건에 따라 다음의 연산자가 제공됩니다.

항목 내용
!= (~C++20) ==을 활용하여 구현되어 있습니다.
>, <=, >= (~C++20) <을 활용하여 구현되어 있습니다.

하지만, C++20 부터 삼중 비교 연산자가 추가되어 모두 deprecate 되었습니다.

기존에는 signedunsigned를 비교하면, signedunsigned암시적으로 형변환 하기 때문에, 음의 정수와 양의 정수를 정상적으로 비교하지 못했습니다.

1
2
3
int x{-1}; // 0xFFFF FFFF(4294967295) 
unsigned int y{1};
EXPECT_TRUE(x < y); // (X) 런타임 오류. -1은 unsigned int로 형변환되어 4294967295입니다.

C++20 부터는 cmp_equal(), cmp_not_equal(), cmp_less(), cmp_greater(), cmp_less_equal(), cmp_greater_equal()이 추가되어 음의 정수와 양의 정수를 정상적으로 비교할 수 있습니다.

항목 내용 constexpr
cmp_equal() (C++20~)
cmp_not_equal() (C++20~)
cmp_less() (C++20~)
cmp_greater() (C++20~)
cmp_less_equal() (C++20~)
cmp_greater_equal() (C++20~)
음의 정수와 양의 정수를 정상적으로 비교 합니다. (C++20~)
in_range<type>(value) (C++20~) 주어진 value가 주어진 type의 값 범위 내에 있는지 검사합니다. (C++20~)

다음은 cmp_less()를 이용하여 음의 정수와 양의 정수를 비교하는 예입니다.

1
2
3
int x{-1}; 
unsigned int y{1};
EXPECT_TRUE(std::cmp_less(x, y)); // (O) 음수와 양수를 정상적으로 비교합니다.  

in_range()는 주어진 value가 주어진 type의 값 범위 내에 있는지 검사합니다.

1
2
static_assert(std::in_range<unsigned int>(-1) == false); // unsigned int 범위 바깥입니다.
static_assert(std::in_range<unsigned int>(1) == true); // unsigned int 범위 입니다. 

(C++11~) 타입 변환

항목 내용 constexpr
move() (C++11~) 좌측값을 우측값으로 형변환 합니다. (C++14~)
move_if_noexcept() (C++11~) nothrow 보증이 되는 경우에만 &&로 형변환 합니다. (C++14~)
forward() (C++11~) 함수가 전달받은 인자를 다른 함수로 완벽하게 전달합니다. (C++14~)
forward_like() (C++23) (작성중)  
declval() (C++11~) 주어진 타입을 참조 타입으로 변환하여, 참조 타입 표현식으로 변경해 줍니다.  
as_const(T& param) (C++17~) 인자 paramconst를 붙여 const T&로 변환합니다. (C++17~)
to_underlying() (C++23~) (작성중) (C++23~)

프로그램 지원

항목 내용
abort() 프로그램을 비정상 종료 시킵니다. terminate() 참고
exit() 프로그램을 정상 종료 시킵니다.
quick_exit() (C++11~) (작성중)
_Exit() (C++11~) (작성중)
atexit() (작성중)
at_quick_exit() (C++11~) (작성중)
EXIT_SUCCESS
EXIT_FALURE
(작성중)
system() (작성중)
getenv() (작성중)
signal() (작성중)
raise() (작성중)
sig_atomic_t (작성중)
SIG_DFL
SIG_IGN
(작성중)
SIG_ERR (작성중)
SIGABRT
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM
(작성중)
setjmp() (작성중)
longjmp() (작성중)
jump_buf() (작성중)
unreachable() (C++23~) 도달할 수 없는 실행 지점을 마킹합니다.

가변 인자

가변 인자를 처리하는 예는 가변 인자를 참고하시기 바랍니다.

항목 내용
va_start() 가변 인자 액세스 시작 매크로 함수
va_arg() 가변 인자 추출 매크로 함수
va_end() 가변 인자 사용 종료 매크로 함수
va_list 가변 인자에 대한 typedef
va_copy (C++11) (작성중)

C스타일 시간 유틸리티

항목 내용
difftime() (작성중)
time() (작성중)
clock() (작성중)
asctime() (작성중)
ctime() (작성중)
strftime() (작성중)
wcsftime() (작성중)
gmtime() (작성중)
localtime() (작성중)
mktime() (작성중)
CLOCKS_PER_SEC (작성중)
tm (작성중)
time_t (작성중)
clock_t (작성중)
timespec_get() (C++17~) timespec 개체를 구합니다.
timespec (C++17~) 초(tv_sec)와 나노초(tv_nsec)로 구분합니다.

(C++17~) 모호성 해소

항목 내용
in_place (C++17~)
in_place_type (C++17~)
in_place_index (C++17~)
in_place_t (C++17~)
in_place_index_t (C++17~)
내부 개체를 생성해서 전달하는 것이 아니라, 내부 개체의 생성자 인수들을 전달하면 내부 개체를 직접 생성하라는 의미로 optional, any, variant 생성자에 전달되는 더미(Dummy) 개체 입니다.

(C++20~) source_location

기존에는 __LINE____FILE__를 이용하여 줄번호와 파일명을 사용했는데요(__LINE__, __FILE__ 참고),

1
2
// Line Number:118 Filename:C:\XXX\XXX.cpp
std::cout << "Line Number:" << __LINE__ << " Filename:" << __FILE__ << std::endl; 

C++20 부터는 source_location이 추가되어 파일명, 줄번호, 칼럼번호, 함수명등의 정보를 제공합니다.

다음의 Log()함수는 메시지와 source_location을 이용한 부가 정보를 출력합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
void Log(std::string message, const std::source_location& location = std::source_location::current()) {

    // Message.
    // source_location : F:\Data\language_test\test\Test_ModernCpp_Utility.cpp, virtual void TestModern_Utility_Test::TestBody()(41, 12)
    std::cout 
        << message << std::endl
        << "source_location : " 
        << location.file_name() << ", " << location.function_name()  // 파일명, 함수명
        << "(" << location.line() << ", " << location.column() << ")"// 줄번호, 칼럼번호
    << std::endl;
}

Log("Message.");    

(C++20~) 삼중 비교

C++20 부터 추가된 삼중 비교 연산자를 지원하는 유틸리티입니다.

항목 내용 constexpr
strong_ordering (C++20~) ==, !=, <, >, <=, >=의 비교 연산을 제공합니다. 여기서 ==상등 비교입니다. 즉 데이터들이 완전히 동일함을 의미합니다.  
weak_ordering (C++20~) ==, !=, <, >, <=, >=의 비교 연산을 제공합니다. 여기서 ==동등 비교를 합니다. 즉, 개념적으로 동일함을 의미합니다. 예를들어 대소문자 구분없이 비교 할때 Aa아스키 코드값이 다르므로 상등하지 않지만, 개념적으로 동등합니다.  
partial_ordering (C++20~) ==, !=, <, >, <=, >=의 비교 연산을 제공합니다. 실수 타입과 같이 대소 비교는 가능한데, ==는 소수점 오차등으로 상등 비교를 신뢰하기 애매한 경우입니다.  
strong_order() (C++20~) 삼중 비교 연산자로 비교 하고 strong_ordering를 리턴합니다. (C++20~)
weak_order() (C++20~) 삼중 비교 연산자로 비교 하고 weak_ordering를 리턴합니다. (C++20~)
partial_order() (C++20~) 삼중 비교 연산자로 비교 하고 partial_ordering를 리턴합니다. (C++20~)
is_eq(), is_neq() (C++20~)
is_lt(), is_lteq(), is_gt(), is_gteq() (C++20~)
삼중 비교 연산자로 비교합니다. (C++20~)
compare_three_way (C++20~) 삼중 비교 연산자로 비교하는 함수자입니다.  
compare_three_way_result (C++20~) 주어진 타입의 삼중 비교 연산자 리턴 타입의 별칭입니다. strong_ordering, weak_ordering, partial_ordering 중 하나입니다.  
common_comparison_category (C++20~) 주어진 타입의 비교 카테고리를 리턴합니다.  
compare_strong_order_fallback() (C++20~) 삼중 비교 연산자가 없는 경우에도 삼중 비교를 합니다. (C++20~)
compare_weak_order_fallback() (C++20~) 삼중 비교 연산자가 없는 경우에도 삼중 비교를 합니다. (C++20~)
compare_partial_order_fallback() (C++20~) 삼중 비교 연산자가 없는 경우에도 삼중 비교를 합니다. (C++20~)

다음은 삼중 비교 관련 유틸리티들의 사용예입니다.

compare_three_way, strong_order()등은 삼중 비교 연산자가 없으면 사용할 수 없으며, compare_strong_order_fallback(), compare_weak_order_fallback(), compare_partial_order_fallback()삼중 비교 연산자가 없는 경우이더라도 삼중 비교를 가능하게 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class T {
private:
    int m_Val;

public:
    explicit T(int val) : m_Val(val) {}

    bool operator ==(const T& other) const {return m_Val == other.m_Val;}
    bool operator <(const T& other) const {return m_Val < other.m_Val;}

    // 삼중 비교 연산자가 없습니다.
    // std::strong_ordering operator<=>(const T& other) const {return m_Val <=> other.m_Val;}
};

// EXPECT_TRUE(T{1} <=> T{2} == 0); // (X) 컴파일 오류. 삼중 비교 연산자가 없습니다.
// EXPECT_TRUE(std::compare_three_way{}(T{1}, T{2}) < 0); // (X) 컴파일 오류. 삼중 비교 연산자가 없습니다.
// EXPECT_TRUE(std::strong_order(T{1}, T{2}) < 0); // (X) 컴파일 오류. 삼중 비교 연산자가 없습니다.
EXPECT_TRUE(std::compare_strong_order_fallback(T{1}, T{2}) < 0); // 삼중 비교 연산자가 없더라도, 삼중 비교를 할 수 있습니다.

(C++20~) 유틸리티의 constexpr 개선

유틸리티에서 점진적으로 constexpr 지원을 개선하고 있습니다.

특히 C++20 부터는 swap()함수도 constexpr 함수로 변경되었습니다.

따라서 다음과 같이 swap()constexpr 함수내에서 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
constexpr std::pair<int, int> ConstSwap(int&& a, int&& b) {
    int resultA{std::move(a)};
    int resultB{std::move(b)};
    
    std::swap(resultA, resultB); // 컴파일 타임에 두 수를 바꿔치기 합니다.
    return std::make_pair(resultA, resultB);
}

constexpr std::pair<int, int> result{ConstSwap(0, 1)};
static_assert(result.first == 1 && result.second == 0);  

(C++20~) STL 지원 테스트

C++20 부터는 STL 지원 테스트 매크로가 추가되어 C++11부터 추가된 STL 기능을 지원하는지 테스트 할 수 있습니다.(언어 지원 테스트 참고)

테스트할 수 있는 항목은 https://en.cppreference.com/w/cpp/feature_test#Library_features를 참고하시기 바랍니다.

1
2
3
4
5
#if __cpp_lib_string_view
    std::cout << "Support string_view" << std::endl; // string_view를 지원합니다.
#else 
    std::cout << "No string_view" << std::endl;
#endif  

태그:

카테고리:

업데이트:

댓글남기기