Files
2025-10-25 03:02:53 +03:00

60 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[const.wrap.class]
# 21 Metaprogramming library [[meta]](./#meta)
## 21.3 Metaprogramming and type traits [[type.traits]](type.traits#const.wrap.class)
### 21.3.5 Class template constant_wrapper [const.wrap.class]
template<class T>struct *cw-fixed-value* { // *exposition only*using *type* = T; // *exposition only*constexpr *cw-fixed-value*(*type* v) noexcept : *data*(v) {} T *data*; // *exposition only*};
template<class T, size_t Extent>struct *cw-fixed-value*<T[Extent]> { // *exposition only*using *type* = T[Extent]; // *exposition only*constexpr *cw-fixed-value*(T (&arr)[Extent]) noexcept;
T *data*[Extent]; // *exposition only*};
template<class T, size_t Extent>*cw-fixed-value*(T (&)[Extent]) -> *cw-fixed-value*<T[Extent]>; // *exposition only*struct *cw-operators* { // *exposition only*// unary operatorstemplate<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>friend constexpr auto operator+(T) noexcept -> constant_wrapper<(+T::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>friend constexpr auto operator-(T) noexcept -> constant_wrapper<(-T::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>friend constexpr auto operator~(T) noexcept -> constant_wrapper<(~T::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>friend constexpr auto operator!(T) noexcept -> constant_wrapper<(!T::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>friend constexpr auto operator&(T) noexcept -> constant_wrapper<(&T::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>friend constexpr auto operator*(T) noexcept -> constant_wrapper<(*T::value)>{ return {}; }// binary operatorstemplate<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator+(L, R) noexcept -> constant_wrapper<(L::value + R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator-(L, R) noexcept -> constant_wrapper<(L::value - R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator*(L, R) noexcept -> constant_wrapper<(L::value * R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator/(L, R) noexcept -> constant_wrapper<(L::value / R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator%(L, R) noexcept -> constant_wrapper<(L::value % R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator<<(L, R) noexcept -> constant_wrapper<(L::value << R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator>>(L, R) noexcept -> constant_wrapper<(L::value >> R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator&(L, R) noexcept -> constant_wrapper<(L::value & R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator|(L, R) noexcept -> constant_wrapper<(L::value | R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator^(L, R) noexcept -> constant_wrapper<(L::value ^ R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>requires (!is_constructible_v<bool, decltype(L::value)> ||!is_constructible_v<bool, decltype(R::value)>)friend constexpr auto operator&&(L, R) noexcept -> constant_wrapper<(L::value && R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>requires (!is_constructible_v<bool, decltype(L::value)> ||!is_constructible_v<bool, decltype(R::value)>)friend constexpr auto operator||(L, R) noexcept -> constant_wrapper<(L::value || R::value)>{ return {}; }// comparisonstemplate<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator<=>(L, R) noexcept -> constant_wrapper<(L::value <=> R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator<(L, R) noexcept -> constant_wrapper<(L::value < R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator<=(L, R) noexcept -> constant_wrapper<(L::value <= R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator==(L, R) noexcept -> constant_wrapper<(L::value == R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator!=(L, R) noexcept -> constant_wrapper<(L::value != R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator>(L, R) noexcept -> constant_wrapper<(L::value > R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator>=(L, R) noexcept -> constant_wrapper<(L::value >= R::value)>{ return {}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator,(L, R) noexcept = delete; template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") L, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>friend constexpr auto operator->*(L, R) noexcept -> constant_wrapper<L::value->*(R::value)>{ return {}; }// call and indextemplate<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]")... Args>constexpr auto operator()(this T, Args...) noexceptrequires requires(Args...) { constant_wrapper<T::value(Args::value...)>(); }{ return constant_wrapper<T::value(Args::value...)>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]")... Args>constexpr auto operator[](this T, Args...) noexcept-> constant_wrapper<(T::value[Args::value...])>{ return {}; }// pseudo-mutatorstemplate<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>constexpr auto operator++(this T) noexceptrequires requires(T::value_type x) { ++x; }{ return constant_wrapper<[] { auto c = T::value; return ++c; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>constexpr auto operator++(this T, int) noexceptrequires requires(T::value_type x) { x++; }{ return constant_wrapper<[] { auto c = T::value; return c++; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>constexpr auto operator--(this T) noexceptrequires requires(T::value_type x) { --x; }{ return constant_wrapper<[] { auto c = T::value; return --c; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T>constexpr auto operator--(this T, int) noexceptrequires requires(T::value_type x) { x--; }{ return constant_wrapper<[] { auto c = T::value; return c--; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator+=(this T, R) noexceptrequires requires(T::value_type x) { x += R::value; }{ return constant_wrapper<[] { auto v = T::value; return v += R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator-=(this T, R) noexceptrequires requires(T::value_type x) { x -= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v -= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator*=(this T, R) noexceptrequires requires(T::value_type x) { x *= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v *= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator/=(this T, R) noexceptrequires requires(T::value_type x) { x /= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v /= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator%=(this T, R) noexceptrequires requires(T::value_type x) { x %= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v %= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator&=(this T, R) noexceptrequires requires(T::value_type x) { x &= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v &= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator|=(this T, R) noexceptrequires requires(T::value_type x) { x |= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v |= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator^=(this T, R) noexceptrequires requires(T::value_type x) { x ^= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v ^= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator<<=(this T, R) noexceptrequires requires(T::value_type x) { x <<= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v <<= R::value; }()>{}; }template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") T, [*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator>>=(this T, R) noexceptrequires requires(T::value_type x) { x >>= R::value; }{ return constant_wrapper<[] { auto v = T::value; return v >>= R::value; }()>{}; }};
template<*cw-fixed-value* X, class>struct constant_wrapper : cw-operators {static constexpr const auto & value = X.*data*; using type = constant_wrapper; using value_type = typename decltype(X)::*type*; template<[*constexpr-param*](meta.type.synop#concept:constexpr-param "21.3.3Header <type_­traits> synopsis[meta.type.synop]") R>constexpr auto operator=(R) const noexceptrequires requires(value_type x) { x = R::value; }{ return constant_wrapper<[] { auto v = value; return v = R::value; }()>{}; }constexpr operator decltype(auto)() const noexcept { return value; }};
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L851)
The class template constant_wrapper aids in metaprogramming by ensuring
that the evaluation of expressions comprised entirely of constant_wrapper are core constant expressions ([[expr.const]](expr.const "7.7Constant expressions")),
regardless of the context in which they appear[.](#1.sentence-1)
In particular, this enables use of constant_wrapper values
that are passed as arguments to constexpr functions to be used in constant expressions[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L859)
[*Note [1](#note-1)*:
The unnamed second template parameter to constant_wrapper is present
to aid argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup"))
in finding overloads for which constant_wrapper's wrapped value is a suitable argument,
but for which the constant_wrapper itself is not[.](#2.sentence-1)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L867)
[*Example [1](#example-1)*: constexpr auto initial_phase(auto quantity_1, auto quantity_2) {return quantity_1 + quantity_2; }constexpr auto middle_phase(auto tbd) {return tbd; }void final_phase(auto gathered, auto available) {if constexpr (gathered == available) std::cout << "Profit!\n"; }void impeccable_underground_planning() {auto gathered_quantity = middle_phase(initial_phase(std::cw<42>, std::cw<13>)); static_assert(gathered_quantity == 55); auto all_available = std::cw<55>;
final_phase(gathered_quantity, all_available); }void deeply_flawed_underground_planning() {constexpr auto gathered_quantity = middle_phase(initial_phase(42, 13)); constexpr auto all_available = 55;
final_phase(gathered_quantity, all_available); // error: gathered == available// is not a constant expression} — *end example*]
[🔗](#itemdecl:1)
`constexpr cw-fixed-value(T (&arr)[Extent]) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L904)
*Effects*: Initialize elements of *data* with corresponding elements of arr[.](#4.sentence-1)