마이너한 기능들은 뺍니다.
C++23 언어 관련 주요 기능들
1. if consteval
- if constexpr의 consteval 버전이 생깁니다.
2. Deducing this
- 이제 클래스에서 똑같은 함수를 non-const, const 버전으로 두 가지를 만드느라 생기는 중복코드가 대폭 간결해집니다.
3. auto(x), auto{x}
- 함수 파라미터에서 rvalue (정확히는 prvalue)로 카피해 전달해주는 기능입니다.
예제) 벡터에서 첫 원소와 똑같은 원소를 다 지우고 싶을때
auto elem = v.front();
std::erase(v.begin(), v.end(), elem);
이 때 auto elem = v.front();에서 무조건 복사가 생깁니다. C++23부터는
std::erase(v.begin(), v.end(), auto(v.front());
로 복사를 막을 수 있습니다.
4. #elifdef, #elifndef, #warning
- 전처리 지시문입니다. 이름 보시면 뭐 하는건지 다 아실 테니 패스
5. operator[]의 다차원 버전 지원
- 이제 N차원 행렬 같은거 짤 때 arr[1, 3, 2, 4]같은 게 가능해집니다.
6. static operator()
이제 함수 오브젝트의 operator()도 static 멤버 함수로 쓸 수 있습니다.
7. [[assume]]
- Contract가 c++20에 들어가려다가 엎어지고, 그걸 함수의 사전조건과 사후조건을 다른 방식으로 표준에 편입시키는 것으로 합의되었는데,
이 중 함수의 사전조건을 컴파일러에게 알려주는 attribute입니다.
C++23 표준 라이브러리 관련 주요 기능들
1. 리플렉션
- 드디어 C++에도 스택 트레이스가 생깁니다.
2. std::spanstream
- 본래 C++의 raw char array 버퍼 관련 입출력 스트림은 std::strstream이었습니다.
이건 90년대 초반에 나온 물건인데, 당시는 RAII 개념도 없었고
std::strstream이 쓰는 char* 버퍼의 메모리 소유권 관리가 매우 해괴한 방식이었기 때문에
std::string이 제대로 보급되고 나서 std::string 기반 std::stringstream을 대신 쓸 것이 권유되고
std::strstream은 무려 24년 전인 C++98에 deprecate 되었습니다.
"deprecate 된게 24년 전인데 왜 아직까지 remove 되지 않았느냐?"
std::string 기반 스트림과 char* 기반 스트림은 동작 방식이 많이 다르고,
char* 기반 스트림이 아무래도 성능 상으로 더 빠를 수밖에 없기 때문에
std::stringstream이 std::strstream을 완전히 대체할 수는 없었습니다.
"아예 없애지는 말아달라. 나는 필요할 때는 잘 쓴다." 라는 사람들이 있지요.
하지만 이제 C++20에 std::span이 추가 되면서 std::span<charT>를
스트림 버퍼로 쓸 수 있게 되었습니다. 이것이 std::spanstream입니다.
std::strstream은 C++26에서 완전히 삭제되어 deprecate 이후 28년만에 마침내 무덤으로 갈 가능성이 높습니다.
3. range 관련 대폭 개선
C++20의 range는 지원되는 기능이 많이 부실한 반쪽짜리였습니다.
이쪽의 본좌인 파이썬과 비교하면, 뭔가 되는게 없다는 느낌이 많이 들죠.
C++23에서는 이를 대폭 개선해 기능상으로는 파이썬 range에 밀리지 않는 수준까지 보강했습니다.
(타이핑해야 하는 글자 수는.. 그건 말씀드리기 싫습니다.)
- ranges::starts_with, ranges::end_with / 파이썬 startswith(), endswith()는 string만 받는데 이건 range를 받습니다.
- ranges::contains / 이게 c++20에 없었다니..
- ranges::iota / 드디어 C++에서도 for i in range(30) 같은 문법이 가능해집니다.
- views::zip / 드디어 C++에도 zip()이 생깁니다.
- views::chunk, views::slide, views::stride
예제)
std::vector v = {1, 2, 3, 4, 5, 6, 7};
fmt::print("{} ", v | std::views::chunk(2)); // [[1, 2], [3, 4], [5, 6], [7]]
fmt::print("{} ", v | std::views::slide(2)); // [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]
fmt::print("{}
", v | std::views::stride(2)); // [1, 3, 5, 7]
- views::repeat / repeat하는 view
- views::cartesian_product / itertools.product()와 같습니다.
- ranges::to / range의 정보를 어떤 컨테이너 같은 곳에다 저장해야 할 때 씁니다.
예제)
auto even = [](int i) { return 0 == i % 2; };
auto v = ranges::iota(30) | views::filter(even) | ranges::to<std::vector<int>>;
하면 0부터 29까지 숫자 중 짝수로 이루어진 std::vector를 한 줄로 만들 수 있습니다.
- views::as_rvalue | rvalue로 casting하는 view
4. 표준 라이브러리의 모듈화 지원
C++20 모듈은 지원하는 컴파일러도 MSVC밖에 없습니다. (근데 버그가 존나 많아서 못써먹을 수준입니다)
MSVC는 표준 라이브러리를 import std.core; 식으로 모듈화 했는데요.
이렇게 헤더들이 어떤 모듈에 들어가는지를 C++23에서는 표준화 합니다.
5. <expected>
예외 처리를 성능 때문에 못 쓰는 사람들은 에러 코드를 써야 합니다.
이를 expected<T, E> 식으로 만들어서, 함수가 성공적으로 수행되었으면 T에 리턴값이 담기고,
아니면 E에 에러 코드가 담기는 방식을 표준에 넣었습니다.
6. <flat_map>, <flat_set>
std::set, std::map보다 lookup은 훨씬 더 빠르고 삽입/삭제는 훨씬 더 느린 정렬 컨테이너입니다.
boost꺼 가져올 가능성이 높은데 boost::container::flat_set, flat_map 삽입 삭제는 거의 못써먹을 정도로 느린데 걱정이 되네요.
7. std::mdspan
다차원 span입니다. 다차원 행렬을 만들 때 가장 빡치는 건 submatrix 짜는 건데,
이를 위해 딱이라고 볼 수 있네요.
8. format output 관련 대폭 개선
C++20의 std::format은 뭔가 안 되는게 많아서 그를 대폭 개선한 std::print 등이 나옵니다.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2286r8.html 에 자세한 예제와 제안자의 한탄이 나오네요.
짱개 폐렴이 잦아드니 C++ 커미티에서도 작업이 쭉쭉 진행되어 가네요.
C++11은 엄청난 혁신이었지만 뭔가 반쪽짜리로 내놓은게 많아서 C++14가 그것을 완성했습니다.
C++20도 엄청난 혁신이었지만 급하게 내놓느라 모듈, 레인지, 포맷, 코루틴 등등 별로 좋은 평을 받고 있지 못해서
(완성도가 높다는 평을 받는건 컨셉 뿐입니다) C++23이 그를 완성하게 될 것 같네요.
std::optional로는 좀 부족하다는 느낌 받았었는데 expected가 나오는구나
optional은 pair T, bool이랑 비슷한 물건이죠. expected는 pair T, error_code랑 비슷한 물건.
expected<T> 랑 result<T>랑 차이가 있나요? - dc App
C++에 result T가 있나요? Rust 말씀하시는 건가
rvalue로 파라미터에 카피하는건 std::move 쓰면 되는거 아님? auto(x) 랑 차이가 머야
위의 예제를 보자면, auto elem = std::move(v.front());를 하는 순간 v 원소가 std::string 같은 거면 v[0]에는 elem이 없고 빈 string이 들어갈 수 있죠. std::erase는 elem이랑 v 원소를 비교해가면서 지우는 건데 그러면 v[0]이 안 지워지게 되죠. std::move를 해서 빈 string이 되니까요
이젠 c++은 뭐가 뭔지 모르겠어
어지럽긴 한데.. 아직은 따라갈만은 하겠다
오히려 사용성은 갈수록 발전하고 있지 않나요? 03->11때가 "이해하기 어려운" 개념들이 제일 많이 추가되었고, 이후에는 사용성은 갈수록 개선되고 있는 것 같습니다. 그 이후에 추가된 이해하기 어려운 개념들은 코루틴 정도..?
누더기골렘...
아주 좋네용
C++은 진짜 단시간에 못배워먹을 물건이긴하네..
11겨우 따라잡았다 싶으니 이리되네 - dc App
정리 굿 ㄱㅅㄱㅅ
deducing this 설명이 흥미로워서 찾아봤는데 python처럼 멤버함수에 self 적어주는거인듯
this를 함수인자로 표기하고 템플릿으로 this의 타입을 퍼펙트 포워딩하면 똑같은거 여러번 안만들어도 됨이라는듯