- utility[meta header]
- std[meta namespace]
- class template[meta id-type]
- cpp26[meta cpp]
- cw[meta alias]
namespace std {
template <auto X, class = decltype(X)>
struct constant_wrapper;
// 型Tが定数として扱えることを表す説明用コンセプト
template <class T>
concept constexpr-param =
requires { typename constant_wrapper<T::value>; };
// すべての演算子オーバーロードを提供する説明用の基底クラス
struct cw-operators;
// constant_wrapperを簡潔に生成する変数テンプレート
template <auto X>
constexpr auto cw = constant_wrapper<X>{};
}constant_wrapperクラステンプレートは、定数Xを型として包むことで、その値を「型の世界」で扱えるようにするためのラッパーである。
constant_wrapperのみで構成された式は、それが現れる文脈に関わらず、常にコア定数式として評価される。これによって、通常はテンプレート引数としてしか渡せない定数を、関数の引数として渡しても定数式として利用できるようになる。とくに、テンプレート引数を明示的に指定できないコンストラクタ呼び出しなどで有用である。
変数テンプレートcwを使うと、std::constant_wrapper<42>{}と書く代わりにstd::cw<42>と簡潔に書ける。
// 通常の定数を関数引数として受け取り、コンパイル時に計算する
constexpr auto add(auto a, auto b)
{
return a + b;
}
auto result = add(std::cw<42>, std::cw<13>); // resultはconstant_wrapper<55>型
static_assert(result == 55); // resultが定数式でなくても、その値は定数式constant_wrapperはあらゆる演算子をオーバーロードしている。オペランドがすべてconstant_wrapperである場合は、演算結果もconstant_wrapperになり、「型の世界」にとどまる。オペランドのいずれかが通常の値である場合は、保持する値にアンラップされて通常の演算がおこなわれる。
クラステンプレートconstant_wrapperの2つめのテンプレートパラメータは無名であり、引数依存の名前探索 (ADL) を補助するために存在する。これによって、包んでいる値が引数として適合するオーバーロードを、constant_wrapper自身が適合しない場合でも発見できるようになる。
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
デフォルトコンストラクタ(暗黙定義) | C++26 |
operator= |
代入(valueがconstのためconstant_wrapperでは不適格) |
C++26 |
operator value_type |
保持する値への変換演算子 | C++26 |
operator() |
保持する値を関数として呼び出す(静的メンバ関数) | C++26 |
operator[] |
保持する値に添字アクセスする(静的メンバ関数) | C++26 |
また、説明用の基底クラスcw-operatorsから以下の擬似的な変更操作を継承する。ただしconstant_wrapperが保持するvalueはconstであるため、これらの演算子と上記operator=は、保持する値そのものを変更する式(++value、value op= x、value = x)が不適格となり、constant_wrapperに対してはオーバーロード解決に参加しない(使用できない)。
| 名前 | 説明 | 対応バージョン |
|---|---|---|
operator++ |
インクリメント | C++26 |
operator-- |
デクリメント | C++26 |
operator+= |
加算の複合代入 | C++26 |
operator-= |
減算の複合代入 | C++26 |
operator*= |
乗算の複合代入 | C++26 |
operator/= |
除算の複合代入 | C++26 |
operator%= |
剰余の複合代入 | C++26 |
operator&= |
ビット論理積の複合代入 | C++26 |
operator|= |
ビット論理和の複合代入 | C++26 |
operator^= |
ビット排他的論理和の複合代入 | C++26 |
operator<<= |
左シフトの複合代入 | C++26 |
operator>>= |
右シフトの複合代入 | C++26 |
| 名前 | 説明 | 対応バージョン |
|---|---|---|
type |
constant_wrapper自身を表す型 |
C++26 |
value_type |
保持する値の型 decltype(X)、すなわちラップした値Xの型 |
C++26 |
たとえばstd::cw<42>(Xはintの42)の場合、typeはstd::constant_wrapper<42>、value_typeはintとなる。
| 名前 | 説明 | 設定される値・型 | 対応バージョン |
|---|---|---|---|
value |
保持する定数値への参照 | テンプレート引数Xへの参照(static constexpr decltype(auto) value = (X);)。型はconst value_type& |
C++26 |
たとえばstd::cw<42>の場合、valueの値は42、その型はconst int&となる。valueはテンプレートパラメータオブジェクトへの参照であるため、ダングリングしない。
非メンバ(Hidden friends)関数
constant_wrapperは、説明用の基底クラスcw-operatorsを継承することで、以下の演算子を Hidden friends として提供する。
いずれの演算子も、オペランドがすべて説明用コンセプトconstexpr-param(constant_wrapperのように、静的メンバvalueを定数として持つ型)のモデルであることを要求し、演算結果を包んだconstant_wrapperを返す。
| 名前 | 説明 | 対応バージョン |
|---|---|---|
operator+ |
単項+ |
C++26 |
operator- |
単項-(符号反転) |
C++26 |
operator~ |
ビット反転 | C++26 |
operator! |
論理否定 | C++26 |
operator& |
単項&(アドレス取得) |
C++26 |
operator* |
単項*(間接参照) |
C++26 |
operator+ |
加算 | C++26 |
operator- |
減算 | C++26 |
operator* |
乗算 | C++26 |
operator/ |
除算 | C++26 |
operator% |
剰余 | C++26 |
operator<< |
左シフト | C++26 |
operator>> |
右シフト | C++26 |
operator& |
ビット論理積 | C++26 |
operator| |
ビット論理和 | C++26 |
operator^ |
ビット排他的論理和 | C++26 |
operator&& |
論理積 | C++26 |
operator|| |
論理和 | C++26 |
operator<=> |
三方比較 | C++26 |
operator< |
左辺が右辺より小さいかの判定 | C++26 |
operator<= |
左辺が右辺以下かの判定 | C++26 |
operator> |
左辺が右辺より大きいかの判定 | C++26 |
operator>= |
左辺が右辺以上かの判定 | C++26 |
operator== |
等値比較 | C++26 |
operator!= |
非等値比較 | C++26 |
operator, |
カンマ演算子(delete定義) |
C++26 |
operator->* |
メンバポインタ参照 | C++26 |
namespace std {
template <auto X>
constexpr auto cw = constant_wrapper<X>{};
}cwは、constant_wrapper<X>のオブジェクトを簡潔に生成するための変数テンプレートである。std::cw<X>はstd::constant_wrapper<X>{}と等価である。
operator()とoperator[]は静的メンバ関数であり、保持する値valueをアンラップして呼び出す。引数がすべてconstexpr-paramのモデルであり、その結果をふたたびconstant_wrapperで包める場合は、包んだconstant_wrapperを返す。そうでない場合は、アンラップした結果をそのまま返す。- この「保持する値そのものになる。ただし包んだままにできるなら包んだままにする」という規則は、すべての演算子に共通する。たとえば、
std::cw<1> + 1はintの2に、std::cw<1> + std::cw<1>はconstant_wrapper<2>になる。
- この「保持する値そのものになる。ただし包んだままにできるなら包んだままにする」という規則は、すべての演算子に共通する。たとえば、
operator,(カンマ演算子)はdelete定義されている。
#include <utility>
#include <iostream>
// 定数を通常の関数引数として受け取り、コンパイル時に計算する高階関数
constexpr auto add(auto a, auto b)
{
return a + b;
}
int main()
{
// cw<42>とcw<13>は、値を型として保持する
auto result = add(std::cw<42>, std::cw<13>);
// resultはconstant_wrapper<55>型であり、
// result自身が定数式でなくても、その値は定数式として使用できる
static_assert(result == 55);
std::cout << result << std::endl;
}- std::cw[color ff0000]
55
#include <utility>
#include <type_traits>
int main()
{
// オペランドがすべてconstant_wrapperなら、演算結果も再びconstant_wrapperになる
auto a = std::cw<10> + std::cw<5>;
static_assert(std::is_same_v<decltype(a), std::constant_wrapper<15>>);
// オペランドのいずれかが通常の値なら、保持する値へアンラップして演算する
auto b = std::cw<10> + 5;
static_assert(std::is_same_v<decltype(b), int>);
}- std::cw[color ff0000]
- std::constant_wrapper[color ff0000]
#include <utility>
#include <iostream>
constexpr int triple(int x) { return x * 3; }
// constant_wrapperはNTTPとして使うために名前空間スコープに置く
constexpr int data[] = {0, 10, 20, 30};
int main()
{
// cw<triple>を関数呼び出しすると、保持する関数を呼び出す
// 引数もconstant_wrapperなら、結果を再びconstant_wrapperで包む
auto r = std::cw<triple>(std::cw<7>);
static_assert(r == 21);
std::cout << r << std::endl;
// 配列を保持して添字アクセスする
auto e = std::cw<data>[std::cw<2>];
static_assert(e == 20);
std::cout << e << std::endl;
}- std::cw[color ff0000]
21
20
- C++26
- Clang: 23 [mark verified]
- GCC: 16.1 [mark verified]
- Visual C++: 2026 Update 2 [mark noimpl]
std::integral_constant型として整数定数を表すクラスstd::function_refメンバ関数ポインタなどを束縛する際にconstant_wrapperを受け取る
- P2781R9
std::constant_wrapper- C++26で
constant_wrapperと変数テンプレートcwが追加された
- C++26で
- P3978R3
constant_wrappershould unwrap on call and subscriptoperator()とoperator[]を静的メンバ関数とし、INVOKEを用いて値をアンラップして呼び出すよう変更された。あわせてconstant_wrapperとcwの定義が<type_traits>から<utility>へ移動した
- P4206R0 Revert string support in
std::constant_wrapper- 文字列リテラルのサポートを削除し、テンプレートパラメータを説明用の
cw-fixed-valueからautoに戻した。これにともないvalue_typeはdecltype(X)、valueはX自身を参照するよう簡略化された。仕様としてはC++29に導入されるが、C++26に対する欠陥報告 (DR) である
- 文字列リテラルのサポートを削除し、テンプレートパラメータを説明用の