728x90

이번에 chrono에 시간관련 라이브러리가 추가되었다

매우 사용하기 쉬우니... 한번 돌려보면 바로 이해 될 듯...

// hh_mm_ss : duration since midnight, split into hours, minutes, seconds, fractional seconds

auto timeOfDay = std::chrono::hh_mm_ss(12.5h + 32min + 100s + 0.6s);
cout << timeOfDay << endl;
cout << timeOfDay.hours() << endl;
cout << timeOfDay.minutes() << endl;
cout << timeOfDay.seconds() << endl;
cout << timeOfDay.subseconds() << endl;
cout << timeOfDay.to_duration() << endl;

// Calendar Date
using namespace chrono;
chrono::year_month_day ymd1{year(2021), month(11), day(14)};
chrono::year_month_day ymd2{year(2021)/month(11)/day(14)};
chrono::year_month_day ymd3{2021y, November, 14d};
cout << ymd1 << endl;
	
// 해당 년/월의 마지막날을 가져오는 방법
// year/month/day
// day/month/year
// month/day/year
std::chrono::year_month_day_last ymdl1 = 2021y / November / last;
std::chrono::year_month_day_last ymdl2 = last / November / 2021y;
std::chrono::year_month_day_last ymdl3 = November / last / 2021;
auto d1 = ymdl1.day();
chrono::year_month_day ymd4{ymdl1};

// 해당 년/월의 4번째 금요일 날짜 가져오는 방법
std::chrono::year_month_weekday ymwkd1{year(2021)/November/Friday[4]};
chrono::year_month_day ymd5{ ymwkd1 };

// timepoint
time_point timePoint = chrono::sys_days(ymd1);

// Cute Syntax
// 2021y, 30d, January, February, ... December

// Validation
std::chrono::day d{31};
d++;
bool valid = d.ok();

auto leapYear2000{year(2000)/2/29};
auto leapYear2001{year(2001)/2/29};
auto leapYear2002{year(2002)/2/29};

bool valid2 = leapYear2000.ok(); // true
bool valid3 = leapYear2001.ok(); // false
bool valid4 = leapYear2002.ok(); // false

auto now = std::chrono::system_clock::now();
auto diff = floor<chrono::hours>(now) - sys_days(1987y / January / 30d);

 

 

728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - format  (0) 2024.01.20
C++20 - Time Zone  (0) 2024.01.20
C++20 - 비트연산  (0) 2024.01.17
C++20 - erase, erase_if  (1) 2023.12.29
C++20 - Template Parameter for Lambda  (0) 2023.12.28
728x90

그 동안 사용했던 비트연산을 요약하면 다음과 같다

enum Type
{
    test = 3
};

unsigned int bit = 0;

// 추가
bit |= (1 << test);

// 포함 여부 확인
bool check = (bit & (1 << test));

// 삭제
bit &= ~(1 << test);

// 토글
bit ^= (1 << test);

 

좀 더 편하게 사용해라고 이번에 C++20에서 비트연산에 대한 다양한 함수들이 추가되었다.

 

엔디안 확인 기능

// 리틀 엔디안, 빅 엔디안 등등을 확인할 수 있다.
if (std::endian::native == std::endian::little)
{
    cout << "little" << endl;
}
else
{
    cout << "big" << endl;
}

 

그 외에 추가된 함수들...

// bit_cast : 새로운 캐스팅
// has_single_bit	: 어떤 숫자가 2^n 형태인지 (2의 거듭제곱)
// popcount : unsigned int 숫자에서 1의 개수
// bit_ceil : 해당 값보다 작지 않은 (2의 거듭제곱)중 제일 작은 것 (floor < num < ceil)
// bit_floor : 해당 값보다 크지 않은 (2의 거듭제곱)중 제일 큰 것 (floor < num < ceil)
// bit_width : 해당 값을 표현하기 위해 필요한 최소 비트 개수
// rotl : bitwise left-rotation
// rotr : bitwise right-rotation
// countl_zero : 제일 큰 비트부터 시작해서, 연속된 0의 개수
// countl_one : 제일 큰 비트부터 시작해서, 연속된 1의 개수
// countr_zero : 제일 작은 비트부터 시작해서, 연속된 0의 개수
// countr_one : 제일 작은 비트부터 시작해서, 연속된 1의 개수

std::uint8_t num = 0b00110010;
cout << boolalpha;

cout << std::has_single_bit(num) << endl; // false
cout << popcount(num) << endl; // 3
cout << std::bitset<8>(std::bit_ceil(num)) << endl; // 0b01000000
cout << std::bitset<8>(std::bit_floor(num)) << endl; // 
cout << std::bit_width(5u) << endl; // width(0x000101) = 3
cout << std::bitset<8>(std::rotl(num, 2)) << endl; // 0b11001000
cout << std::bitset<8>(std::rotr(num, 2)) << endl; // 0b10001100
cout << countl_zero(num) << endl; // 2
cout << countl_one(num) << endl; // 0
cout << countr_zero(num) << endl; // 1
cout << countr_one(num) << endl; // 0
728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - Time Zone  (0) 2024.01.20
C++20 - Calendar  (0) 2024.01.17
C++20 - erase, erase_if  (1) 2023.12.29
C++20 - Template Parameter for Lambda  (0) 2023.12.28
C++20 - NonType Template Parameter  (0) 2023.12.28
728x90

우리가 STL에서 어떤 요소를 삭제하려면 굉장히 귀찮은 작업을 했었다.

기존의 STL Vector에서의 요소 삭제 코드

int main()
{
    std::vector<int> vec = { -1, 1, -2, 2, -3, 3};
    
    for (auto it = vec.begin(); it != vec.end();)
    {
        auto value = *it;
        if (value < 0)
        {
            it = vec.erase(it);
        }
        else
        {
            ++it;
        }
    }
    
    return 0;
}

위와 같이 삭제 코드가 굉장히 길고 실수할 여지가 다분하다.

 

그래서 뒤에 나온 remove_if를 이용해서 삭제를 했었다.

int main()
{
    std::vector<int> vec = { -1, 1, -2, 2, -3, 3 };
    auto newEnd = std::remove_if(vec.begin(), vec.end(), [](int n) { return n < 0; });
    vec.erase(newEnd, vec.end());
    
    return 0;
}

 

드디어 erase_if가 나와서 좀 더 편하게 사용할 수 있다.

int main()
{
    std::vector<int> vec = { -1, 1, -2, 2, -3, 3 };
    
    std::erase(vec, 2); // 2만 삭제.
    std::erase_if(vec, [](int n) { return n < 0; }); // 0보다 작은 것들 삭제.

    return 0;
}
728x90
728x90

C++11 Typed Lambda

auto sumTyped = [](int a, int b) { return a + b; }

 

C++14 Generic Lambda

auto sumGeneric = [](auto a, auto b) { return a + b; }

 

위의 Lambda도 그 동안 편하게 사용하고 있었는데 이제는 템플릿을 이용해서 사용할 수 있게 되었다.

auto sumTemplate = []<template T>(T a, T b) { return a + b; }
728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - 비트연산  (0) 2024.01.17
C++20 - erase, erase_if  (1) 2023.12.29
C++20 - NonType Template Parameter  (0) 2023.12.28
C++20 - Conditionally Explicit Constructor (조건부 Explicit 생성자)  (1) 2023.12.27
C++20 - constinit  (2) 2023.12.27
728x90

우리가 알고 있는 template를 선언할 때는 아래와 같다

template<typename T>

 

여기에서 typename 대신에 NonType으로 다음과 같이 사용이 가능했다.

int, enum, pointer, reference, nullptr_t 등은 기존에도 사용이 가능했다.

template<int T>

 

이번 C++20에서는 몇가지를 더 사용할 수 있게 되었다.

- Floating-point
- Literal Type (types of constexpr variables)
- String Literal

 

Floating-point를 사용하는 예제

template<double d>
auto GetDouble()
{
   return d;
}

int main()
{
    auto d1 = GetDouble<5.5>();

    return 0;
}

 

Literal Type (types of constexpr variables)을 사용하는 예제

struct ClassType
{
    constexpr ClassType(int) {}
}

template<ClassType t>
auto GetClassType()
{
    return t;
}

int main()
{
    auto t1 = GetClassType<1>();

    return 0;
}

 

String Literal

template<int N>
class StringLiteral
{
public:
    constexpr StringLiteral(char const (&str)[N])
    {
        std::copy(str, str+N, _data);
    }
    
    char _data[N];
}

template<StringLiteral str>
class ClassTemplate {};

template<StringLiteral str>
void FunctionTemplate()
{
    cout << str data << endl;
}

int main()
{
    ClassTemplate<"Hello World"> cls1;
    FunctionTemplate<"Hello">();

    return 0;
}
728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - erase, erase_if  (1) 2023.12.29
C++20 - Template Parameter for Lambda  (0) 2023.12.28
C++20 - Conditionally Explicit Constructor (조건부 Explicit 생성자)  (1) 2023.12.27
C++20 - constinit  (2) 2023.12.27
C++20 - consteval  (1) 2023.12.27
728x90

explicit 키워드는 알고 있다시피 명시적으로 생성자를 호출하겠다는 의미이다.

조건부 explicit 생성자 키워드는 template를 사용할 때 편하게 이용할 수 있을 것 같다.

 

strcut A
{
    template<typename T>
    explicit(!std::is_same<T, bool>::value) A(T t)
    {
        cout << typeid(t).name() << endl;
    }
}

void TestA(A a)
{
}

int main()
{
    A a(true);
    TestA(a);     // 기본적으로 성공
    TestA(true);  // 조건이 맞기 때문에 성공
    TestA(10);    // 조건이 틀리므로 실패
    
    return 0;
}
728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - Template Parameter for Lambda  (0) 2023.12.28
C++20 - NonType Template Parameter  (0) 2023.12.28
C++20 - constinit  (2) 2023.12.27
C++20 - consteval  (1) 2023.12.27
C++20 - 지정된 초기화 (Designated Initialization)  (1) 2023.12.17
728x90

constinit은 CompileTime에 상수로 사용하지만, 일반적인 const와는 다르게 변수처럼 사용이 가능하다

특징

1. CompileTime에 상수로 지정된다.
2. constness는 없다. (즉, 값을 변경할 수 있다)
3. global, static, thread_local 변수에서 사용해야된다. (즉, 일반 변수에는 사용할 수 없다)

위의 특징 중에 "값을 변경할 수 있다." 이 부분이 굉장히 특이하다.

 

아래의 코드와 같이 globalA의 값이 상수임에도 변경해서 사용할 수 있다.

constinit int globalA = 10;
constexpr int globalB = 20;

int main()
{
    globalA = 11; // 성공
    globalB = 21; // 이건 에러
    return 0;
}

 

하지만, 이걸 사용할 일이 있을지는 의문이든다. const를 사용한다는건 기본적으로 상수로 보장시키기 위한 것 아닌가...?

728x90
728x90

consteval은 Compile Time은 오래 걸리더라도 미리 계산을 다 해놓겠다고 지정하는 것이라고 생각 하면된다.

 

우리 모두가 알고 있듯이 아래 함수는 RunTime에 계산이 된다 

int Square(int n)
{
    return n * n;
}

하지만 다음과 같이 consteval 키워드를 붙여주면 컴파일 타임에 계산이되어서 상수로 들어가게된다.

consteval int SquareConstEval(int n)
{
    return n * n;
}

 

무슨 말인가하면 프로그램을 디스어셈블리로 확인해보면 좀 더 쉽게 확인할 수 있다.

위에 사진을 보면 Square(10)의 경우 어셈블리로 move, call, move가 RunTime에 직접 계산이 된 것을 확인 할 수 있지만, 아래 SquareConstEval(10)의 경우에는 mov 어셈블리 밖에 없다 왜냐하면 CompileTime에 이미 계산이 된 채로

"int b = 100;" 으로 변경이 된 상태이기 때문이다.

728x90

+ Recent posts