Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
<format> : basic_format_stringクラスを追加 (close #1097)
- Loading branch information
1 parent
4d92044
commit f770ec5
Showing
12 changed files
with
307 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# basic_format_string | ||
* format[meta header] | ||
* class[meta id-type] | ||
* std[meta namespace] | ||
* cpp23[meta cpp] | ||
|
||
```cpp | ||
namespace std { | ||
template <class charT, class... Args> | ||
struct basic_format_string; | ||
|
||
template <class... Args> | ||
using format_string = basic_format_string<char, type_identity_t<Args>...>; | ||
|
||
template <class... Args> | ||
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>; | ||
} | ||
``` | ||
* type_identity_t[link /reference/type_traits/type_identity.md] | ||
## 概要 | ||
`basic_format_string`クラスは、コンパイル時の書式文字列を表すクラスである。 | ||
C++20までは説明専用クラス`basic-format-string`として定義されていたが、C++23からはユーザーが利用できる正式な機能として定義される。 | ||
このクラスは、書式文字列のコンパイル時チェックを行う。 | ||
```cpp | ||
auto str = std::format("{:d}", "I am not a number"); // コンパイルエラー! | ||
// 書式文字列は「d」で整数を要求しているが、引数として文字列が渡された | ||
``` | ||
|
||
このクラスのコンストラクタは、パラメータの書式文字列と、クラステンプレートパラメータの`Args...`を照合し、 | ||
|
||
- 書式文字列の型チェック | ||
- 開きカッコと閉じカッコの一致 | ||
- その他、型ごとに許可されたオプションが正しいか | ||
|
||
などをチェックする。 | ||
|
||
C++23で説明専用クラスでなく正式な機能として定義されたことにより、以下のように書式化を含むロギングなどをユーザーが定義できるようになる。 | ||
|
||
```cpp | ||
template <typename... Args> | ||
void log(std::format_string<Args...> s, Args&&... args) { | ||
if (logging_enabled) { | ||
log_raw(std::format(s, std::forward<Args>(args)...)); | ||
} | ||
} | ||
``` | ||
* std::format[link /reference/format/format.md] | ||
* std::forward[link /reference/utility/forward.md] | ||
## メンバ関数 | ||
| 名前 | 説明 | 対応バージョン | | ||
|-----------------|----------------|----------------| | ||
| [`(constructor)`](basic_format_string/op_constructor.md) | コンストラクタ | C++23 | | ||
| [`get`](basic_format_string/get.md) | 書式文字列を取得する | C++23 | | ||
## 例 | ||
```cpp example | ||
#include <iostream> | ||
#include <format> | ||
#include <chrono> | ||
thread_local bool logging_enabled = true; | ||
// 現在時刻付きで、文字列フォーマットしてログ出力する | ||
template <typename... Args> | ||
void log(std::format_string<Args...> s, Args&&... args) { | ||
if (!logging_enabled) { | ||
return; | ||
} | ||
namespace chrono = std::chrono; | ||
auto now = chrono::floor<chrono::seconds>(chrono::system_clock::now()); | ||
std::cout << std::format("{}: {}", | ||
chrono::zoned_time{"Asia/Tokyo", now}, | ||
std::format(s, std::forward<Args>(args)...) | ||
) << std::endl; | ||
} | ||
int main() | ||
{ | ||
log("Hello {} World", 42); | ||
} | ||
``` | ||
* std::format_string[color ff0000] | ||
* chrono::system_clock[link /reference/chrono/system_clock.md] | ||
* now[link /reference/chrono/system_clock/now.md] | ||
* chrono::floor[link /reference/chrono/time_point/floor.md] | ||
* chrono::seconds[link /reference/chrono/duration_aliases.md] | ||
* chrono::zoned_time[link /reference/chrono/zoned_time.md] | ||
* std::forward[link /reference/utility/forward.md] | ||
|
||
### 出力 | ||
``` | ||
2023-02-06 10:46:53: Hello 42 World | ||
``` | ||
|
||
## バージョン | ||
### 言語 | ||
- C++23 | ||
|
||
### 処理系 | ||
- [Clang](/implementation.md#clang): ?? | ||
- [GCC](/implementation.md#gcc): 13.1 | ||
- [Visual C++](/implementation.md#visual_cpp): ?? | ||
|
||
## 参照 | ||
- [P2508R1 Expose `std::basic-format-string<charT, Args...>`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2508r1.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# get | ||
* format[meta header] | ||
* function[meta id-type] | ||
* std[meta namespace] | ||
* basic_format_string[meta class] | ||
* cpp23[meta cpp] | ||
|
||
```cpp | ||
constexpr basic_string_view<charT> get() const noexcept; // (1) | ||
``` | ||
|
||
## 概要 | ||
書式文字列を取得する。 | ||
|
||
|
||
## 戻り値 | ||
メンバ変数として`basic_string_view<charT> str;`が定義されるとして、 | ||
|
||
```cpp | ||
return str; | ||
``` | ||
|
||
|
||
## 例 | ||
```cpp example | ||
#include <cassert> | ||
#include <format> | ||
|
||
template <class... Args> | ||
void f(std::format_string<Args...> fmt, Args&&...) { | ||
assert(fmt.get() == "Hello {} World"); | ||
} | ||
|
||
int main() { | ||
f("Hello {} World", 42); | ||
} | ||
``` | ||
* fmt.get()[color ff0000] | ||
## バージョン | ||
### 言語 | ||
- C++23 | ||
### 処理系 | ||
- [Clang](/implementation.md#clang): ?? | ||
- [GCC](/implementation.md#gcc): 13.1 | ||
- [Visual C++](/implementation.md#visual_cpp): ?? | ||
## 参照 | ||
- [P2508R1 Expose `std::basic-format-string<charT, Args...>`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2508r1.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# コンストラクタ | ||
* format[meta header] | ||
* function[meta id-type] | ||
* std[meta namespace] | ||
* basic_format_string[meta class] | ||
* cpp23[meta cpp] | ||
|
||
```cpp | ||
template <class T> | ||
consteval basic_format_string(const T& s); | ||
``` | ||
## 概要 | ||
`basic_format_string`オブジェクトを構築する。 | ||
## テンプレートパラメータ制約 | ||
- `const T&`は[`convertible_to`](/reference/concepts/convertible_to.md)`<`[`basic_string_view`](/reference/string_view/basic_string_view.md)`<charT>>`のモデルであること | ||
## 効果 | ||
メンバ変数として`basic_string_view<charT> str;`が定義されるとして、`str(s)`で初期化する。 | ||
## 備考 | ||
- この関数の呼び出しは、`str`が`args`の書式文字列であるような`Args`型の`args`が存在しない限り、コア定数式ではない | ||
- 意味 : 書式文字列が引数列`args`と合わせて正しくなければ、定数式評価 (`consteval`) が実行できずコンパイルエラーとなる | ||
- 以下のようなコードはコンパイルエラーとなる: | ||
```cpp | ||
int main() { | ||
auto str = std::format("{:d}", "I am not a number"); // コンパイルエラー!型が合わない | ||
} | ||
``` | ||
* std::format[link /reference/format/format.md] | ||
|
||
|
||
## 実装例 | ||
```cpp | ||
// 書式文字列のチェック | ||
template <class CharT, class... Args> | ||
consteval void fmt_checker(std::basic_string_view<CharT> str) | ||
{ | ||
// … | ||
|
||
if (/*カッコの開き・閉じが一致しない場合*/) { | ||
throw "invalid brackets"; // throw式は定数式で実行できないため、 | ||
// このパスを通ったらコンパイルエラーになる | ||
} | ||
|
||
// … | ||
|
||
if (/*型が合わない時*/) { | ||
throw "invalid type specifier"; | ||
} | ||
|
||
// … | ||
} | ||
|
||
namespace std { | ||
template <class CharT, class... Args> | ||
struct basic_format_string { | ||
std::basic_string_view<CharT> str; | ||
|
||
template <class T> | ||
requires std::convertible_to<const T&, std::basic_string_view<charT>> | ||
consteval basic_format_string(const T& s) | ||
: str(s) | ||
{ | ||
fmt_checker<CharT, Args...>(str); | ||
} | ||
}; | ||
|
||
template <class... Args> | ||
using format_string = basic_format_string<char, std::type_identity_t<Args>...>; | ||
} | ||
``` | ||
* std::convertible_to[link /reference/concepts/convertible_to.md] | ||
* std::type_identity_t[link /reference/type_traits/type_identity.md] | ||
## バージョン | ||
### 言語 | ||
- C++23 | ||
### 処理系 | ||
- [Clang](/implementation.md#clang): ?? | ||
- [GCC](/implementation.md#gcc): 13.1 | ||
- [Visual C++](/implementation.md#visual_cpp): ?? | ||
## 参照 | ||
- [P2216R3 `std::format` improvements](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2216r3.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.