Skip to content

Commit

Permalink
<format> : コンテナアダプタの文字列フォーマットに対応 #1085
Browse files Browse the repository at this point in the history
  • Loading branch information
faithandbrave committed Jan 26, 2023
1 parent fd14d85 commit 1971c4d
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 1 deletion.
2 changes: 2 additions & 0 deletions reference/format.md
Expand Up @@ -34,6 +34,8 @@
| [`wformat_context`](format/basic_format_context.md) | `basic_format_context`のワイド文字列版 (type-alias) | C++20 |
| [`range_format`](format/range_format.md) | Rangeの書式種別 (enum) | C++23 |
| [`format_kind`](format/format_kind.md) | 指定したRangeの書式種別を取得する (variable) | C++23 |
| [`const-formattable-range`](format/const-formattable-range.md) | `const Range`の要素型が文字列フォーマット可能 (concept) | C++23 |
| [`fmt-maybe-const`](format/fmt-maybe-const.md) | `formatter::format()`関数のパラメータ型として使用するための(const) Range型を取得 (type-alias) | C++23 |
| [`range_formatter`](format/range_formatter.md) | Rangeに対する書式文字列の解析、値のフォーマットを行う (class template) | C++23 |
| [`range-default-formatter`](format/range-default-formatter.md.nolink) | Rangeに対する共通の書式文字列の解析、値のフォーマットを行う説明専用クラス (class template) | C++23 |

Expand Down
38 changes: 38 additions & 0 deletions reference/format/const-formattable-range.md
@@ -0,0 +1,38 @@
# const-formattable-range
* format[meta header]
* concept[meta id-type]
* std[meta namespace]
* cpp23[meta cpp]

```cpp
namespace std {
template <class R, class charT>
concept const-formattable-range =
ranges::input_range<const R> &&
formattable<ranges::range_reference_t<const R>, charT>;
}
```
* ranges::input_range[link /reference/ranges/input_range.md]
* formattable[link formattable.md]
* ranges::range_reference_t[link /reference/ranges/range_reference_t.md]
## 概要
`const-formattable-range`は、`const R`入力Rangeの要素型が文字列フォーマット可能であることを表す説明専用コンセプトである。
## バージョン
### 言語
- C++23
### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [Visual C++](/implementation.md#visual_cpp): ??
## 関連項目
- [`fmt-maybe-const`](fmt-maybe-const.md)
## 参照
- [P2286R8 Formatting Ranges](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2286r8.html)
32 changes: 32 additions & 0 deletions reference/format/fmt-maybe-const.md
@@ -0,0 +1,32 @@
# fmt-maybe-const
* format[meta header]
* concept[meta id-type]
* std[meta namespace]
* cpp23[meta cpp]

```cpp
namespace std {
template <class R, class charT>
using fmt-maybe-const =
conditional_t<const-formattable-range<R, charT>, const R, R>;
}
```
* const-formattable-range[link const-formattable-range.md]
* conditional_t[link /reference/type_traits/conditional.md]
## 概要
`fmt-maybe-const`は、[`formatter::format()`](/reference/format/formatter/format.md)関数のパラメータ型として使用するための(const) Range型を取得する、型の別名である。
## バージョン
### 言語
- C++23
### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): ??
- [Visual C++](/implementation.md#visual_cpp): ??
## 参照
- [P2286R8 Formatting Ranges](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2286r8.html)
58 changes: 58 additions & 0 deletions reference/format/format.md
Expand Up @@ -170,6 +170,7 @@ Range・シーケンスコンテナに対して使用できる標準のオプシ
- コンテナが[`std::vector`](/reference/vector/vector.md)`<bool>`である場合、その要素型は`bool`として処理される
- Range・シーケンスコンテナでは、要素型がデバッグ出力可能である場合、それがデフォルトで有効となる
- 要素型の書式を指定して、デバッグ出力指定をしなければ、デフォルトで有効になっているデバッグ出力を解除できる
- コンテナアダプタである[`std::queue`](/reference/queue/queue.md)[`std::priority_queue`](/reference/queue/priority_queue.md)[`std::stack`](/reference/stack/stack.md)も使用できる


#### <a id="assoc-format-options" href="#assoc-format-options">連想コンテナの書式 (C++23)</a>
Expand Down Expand Up @@ -446,6 +447,63 @@ int main()
(3, "hello")
```

### コンテナアダプタを出力する (C++23)
```cpp example
#include <iostream>
#include <format>
#include <queue>
#include <stack>
#include <flat_map>
#include <flat_set>

int main()
{
std::queue<int> que;
que.push(1);
que.push(2);
que.push(3);

std::priority_queue<int> pque;
pque.push(1);
pque.push(2);
pque.push(3);

std::stack<int> st;
st.push(1);
st.push(2);
st.push(3);

std::flat_map<int, std::string> m {{1, "aaa"}, {2, "bbb"}};
std::flat_set<int> s = {1, 2, 3};

// queue/priority_queue/stackは、内部で使用しているコンテナと同じ扱い
std::cout << std::format("queue: {}", que) << std::endl;
std::cout << std::format("priority_queue: {}", pque) << std::endl;
std::cout << std::format("stack: {}", st) << std::endl;

// flat_map/flat_setはmap/setと同じ扱い
std::cout << std::format("flat_map: {}", m) << std::endl;
std::cout << std::format("flat_set: {}", s) << std::endl;
}
```
* std::queue[link /reference/queue/queue.md]
* que.push[link /reference/queue/queue/push.md]
* std::priority_queue[link /reference/queue/priority_queue.md]
* pque.push[link /reference/queue/priority_queue/push.md]
* std::stack[link /reference/stack/stack.md]
* st.push[link /reference/stack/stack/push.md]
* std::flat_map[link /reference/flat_map/flat_map.md.nolink]
* std::flat_set[link /reference/flat_map/flat_set.md.nolink]

#### 出力
```
[1, 2, 3]
[3, 2, 1]
[1, 2, 3]
{1: "aaa", 2: "bbb"}
{1, 2, 3}
```

## 実装例
```cpp
template<class... Args>
Expand Down
7 changes: 7 additions & 0 deletions reference/format/formatter.md
Expand Up @@ -18,6 +18,12 @@ namespace std {

template <class charT, formattable<charT>... Ts>
struct formatter<pair-or-tuple<Ts...>, charT>; // (3) C++23

template <class charT,
class T,
formattable<charT> Container,
class... U>
struct formatter<adaptor-type<T, Container, U...>, charT>; // (4) C++23
}
```
* ranges::input_range[link /reference/ranges/input_range.md]
Expand All @@ -33,6 +39,7 @@ namespace std {
- (1) : デフォルトのフォーマット
- (2) : Range用のフォーマット。実装は[`range-default-formatter`](range-default-formatter.md.nolink)クラスが行う
- (3) : [`std::pair`](/reference/utility/pair.md)と[`std::tuple`](/reference/tuple/tuple.md)に対する特殊化
- (4) : コンテナアダプタである[`std::queue`](/reference/queue/queue.md)、[`std::priority_queue`](/reference/queue/priority_queue.md)、[`std::stack`](/reference/stack/stack.md)に対する特殊化
(1)は、`charT`を`char`または`wchar_t`とすると、標準で以下の特殊化が利用できる。
Expand Down
22 changes: 21 additions & 1 deletion reference/format/formatter/format.md
Expand Up @@ -6,15 +6,26 @@
* cpp20[meta cpp]

```cpp
using maybe-const-adaptor =
fmt-maybe-const<adaptor-type<T, Container, U...>, charT>; // 説明専用

template <class FormatContext>
typename FormatContext::iterator
format(T& x, FormatContext& ctx) const;
format(T& x, FormatContext& ctx) const; // (1) C++20

template<class FormatContext>
typename FormatContext::iterator
format(maybe-const-adaptor& r, FormatContext& ctx) const; // (2) C++23
```
* FormatContext[link /reference/format/basic_format_context.md]
* fmt-maybe-const[link /reference/format/fmt-maybe-const.md]
## 概要
受け取った型`T`のオブジェクトを書式化する。
- (1) : デフォルトの`formatter`および、[`std::pair`](/reference/utility/pair.md)と[`std::tuple`](/reference/tuple/tuple.md)に対する`formatter`の特殊化でのシグニチャ
- (2) : コンテナアダプタに対する特殊化でのシグニチャ
## 効果
- [`parse()`](parse.md)メンバ関数で解析した書式文字列の指定に基づいて、`x`の値を文字列に変換する
Expand All @@ -24,6 +35,15 @@ typename FormatContext::iterator
- `I != 0`であれば区切り文字を出力する
- タプルの`I`番目の要素を、その型の`formatter`で出力する
- 閉じカッコを出力する
- コンテナアダプタに対する特殊化の場合、メンバとして以下を持っているとして、
```cpp
formatter<Container, charT> underlying_;
```

- 以下と等価:
```cpp
return underlying_.format(r.c, ctx);
```


## 戻り値
Expand Down
9 changes: 9 additions & 0 deletions reference/format/formatter/parse.md
Expand Up @@ -23,6 +23,15 @@ constexpr typename ParseContext::iterator
- 全体の囲み文字を、[`set_brackets()`](set_brackets.md)メンバ関数で設定する
- 要素の区切り文字を、[`set_separator()`](set_separator.md)メンバ関数で設定する
- 各要素の`formatter`を`e`として、[`e.set_debug_format()`](set_debug_format.md)が有効な式であれば、それを呼び出してデバッグ書式を有効にする
- コンテナアダプタに対する特殊化の場合、メンバとして以下を持っているとして、
```cpp
formatter<Container, charT> underlying_;
```

- 以下と等価:
```cpp
return underlying_.parse(ctx);
```


## 戻り値
Expand Down

0 comments on commit 1971c4d

Please sign in to comment.