はじめに
C++23はC++20の改善版で、より使いやすい機能が追加されている。
特にstd::printは「やっとか!」って感じ。cout << ... << endlの呼吸からやっと解放される。
※ 一部機能はコンパイラのサポート状況により使用できない場合があるよ。
1. std::print / std::println
coutの代わりに:
#include <print>
int x = 42;
string name = "World";
std::print("Hello, {}!", name); // 改行なし
std::println("The answer is {}", x); // 改行あり
// cout より簡潔
// cout << "Hello, " << name << "!" << endl; // 従来
2. deducing this
メンバ関数でthisの型を推論:
struct MyClass {
// 従来:const/非const版を両方書く必要があった
// int& get() { return value; }
// const int& get() const { return value; }
// C++23:1つで両方対応
template<typename Self>
auto& get(this Self& self) {
return self.value;
}
int value;
};
MyClass obj;
const MyClass cobj;
obj.get() = 10; // int&
auto v = cobj.get(); // const int&
CRTP の簡略化
// 従来のCRTP
template<typename Derived>
struct Base {
void interface() {
static_cast<Derived*>(this)->impl();
}
};
// C++23
struct Base {
template<typename Self>
void interface(this Self& self) {
self.impl();
}
};
3. [[assume]] 属性
最適化のヒントを与える:
int divide(int a, int b) {
[[assume(b != 0)]]; // bは0でないと仮定
return a / b; // ゼロ除算チェックを省略できる
}
void process(int* ptr) {
[[assume(ptr != nullptr)]];
// nullチェック省略可能
}
4. if consteval
constevalコンテキストかどうかを判定:
constexpr int compute(int n) {
if consteval {
// コンパイル時評価
return n * n;
} else {
// 実行時評価
return some_runtime_function(n);
}
}
5. std::expected
エラーハンドリングの新しい方法:
#include <expected>
std::expected<int, string> parse_int(string_view s) {
try {
return stoi(string(s));
} catch (...) {
return unexpected("Parse error");
}
}
auto result = parse_int("42");
if (result) {
cout << *result << endl;
} else {
cout << "Error: " << result.error() << endl;
}
// value_or
cout << result.value_or(-1) << endl;
6. std::mdspan
多次元配列ビュー:
#include <mdspan>
int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// 3x4 の2次元ビュー
std::mdspan m(data, 3, 4);
m[1, 2] = 100; // 2行3列目にアクセス
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
cout << m[i, j] << " ";
}
cout << endl;
}
7. std::generator
コルーチンベースのジェネレータ:
#include <generator>
std::generator<int> fibonacci() {
int a = 0, b = 1;
while (true) {
co_yield a;
int temp = a;
a = b;
b = temp + b;
}
}
for (int n : fibonacci() | views::take(10)) {
cout << n << " "; // 0 1 1 2 3 5 8 13 21 34
}
8. ranges の拡張
zip
vector<int> nums = {1, 2, 3};
vector<string> names = {"a", "b", "c"};
for (auto [n, name] : views::zip(nums, names)) {
cout << n << ": " << name << endl;
}
enumerate
vector<string> items = {"apple", "banana", "cherry"};
for (auto [i, item] : views::enumerate(items)) {
cout << i << ": " << item << endl;
}
// 0: apple
// 1: banana
// 2: cherry
chunk / slide
vector<int> nums = {1, 2, 3, 4, 5, 6};
// chunk: グループに分割
for (auto chunk : nums | views::chunk(2)) {
// {1, 2}, {3, 4}, {5, 6}
}
// slide: スライディングウィンドウ
for (auto window : nums | views::slide(3)) {
// {1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}
}
9. std::stacktrace
スタックトレースを取得:
#include <stacktrace>
void foo() {
auto trace = std::stacktrace::current();
cout << trace << endl;
}
10. string の resize_and_overwrite
効率的な文字列操作:
string s;
s.resize_and_overwrite(100, [](char* buf, size_t n) {
// bufに直接書き込み
strcpy(buf, "Hello");
return 5; // 実際の長さを返す
});
11. to_underlying
enumの基底型へ変換:
enum class Color : int { Red = 1, Green = 2, Blue = 3 };
auto val = std::to_underlying(Color::Red); // 1
// static_cast<int>(Color::Red) より簡潔
12. std::unreachable
到達不能を明示:
int foo(int x) {
switch (x) {
case 1: return 10;
case 2: return 20;
default:
std::unreachable(); // ここには到達しない
}
}
13. constexpr の更なる拡張
// unique_ptr が constexpr で使用可能
constexpr auto make_value() {
auto p = make_unique<int>(42);
return *p;
}
constexpr int val = make_value();
14. std::byteswap
エンディアン変換:
#include <bit>
uint32_t x = 0x12345678;
uint32_t y = std::byteswap(x); // 0x78563412
コンパイラサポート状況
| 機能 | GCC | Clang | MSVC |
|---|---|---|---|
print |
14+ | 17+ | 部分的 |
| deducing this | 14+ | 18+ | 19.32+ |
expected |
12+ | 16+ | 19.33+ |
mdspan |
14+ | 17+ | 部分的 |
| ranges拡張 | 14+ | 17+ | 部分的 |
まとめ
| 機能 | 説明 |
|---|---|
print/println |
簡潔な出力 |
| deducing this | thisの型推論 |
[[assume]] |
最適化ヒント |
expected |
エラーハンドリング |
mdspan |
多次元配列ビュー |
generator |
コルーチンジェネレータ |
zip/enumerate |
ranges拡張 |
stacktrace |
スタックトレース取得 |
unreachable |
到達不能マーク |