- tmp/tmpmvupy_aw/{from.md → to.md} +549 -157
tmp/tmpmvupy_aw/{from.md → to.md}
RENAMED
|
@@ -10,35 +10,38 @@ taxonomy of all possible C++types, and state where in that taxonomy a
|
|
| 10 |
given type belongs. The type property inspection traits allow important
|
| 11 |
characteristics of types or of combinations of types to be inspected.
|
| 12 |
The type transformations allow certain properties of types to be
|
| 13 |
manipulated.
|
| 14 |
|
|
|
|
|
|
|
|
|
|
| 15 |
### Requirements <a id="meta.rqmts">[[meta.rqmts]]</a>
|
| 16 |
|
| 17 |
A *UnaryTypeTrait* describes a property of a type. It shall be a class
|
| 18 |
template that takes one template type argument and, optionally,
|
| 19 |
additional arguments that help define the property being described. It
|
| 20 |
shall be `DefaultConstructible`, `CopyConstructible`, and publicly and
|
| 21 |
-
unambiguously derived, directly or indirectly, from its
|
| 22 |
-
*
|
| 23 |
`integral_constant` ([[meta.help]]), with the arguments to the template
|
| 24 |
`integral_constant` determined by the requirements for the particular
|
| 25 |
-
property being described. The member names of the
|
| 26 |
shall not be hidden and shall be unambiguously available in the
|
| 27 |
-
UnaryTypeTrait.
|
| 28 |
|
| 29 |
A *BinaryTypeTrait* describes a relationship between two types. It shall
|
| 30 |
be a class template that takes two template type arguments and,
|
| 31 |
optionally, additional arguments that help define the relationship being
|
| 32 |
described. It shall be `DefaultConstructible`, `CopyConstructible`, and
|
| 33 |
publicly and unambiguously derived, directly or indirectly, from its
|
| 34 |
-
*
|
| 35 |
`integral_constant` ([[meta.help]]), with the arguments to the template
|
| 36 |
`integral_constant` determined by the requirements for the particular
|
| 37 |
-
relationship being described. The member names of the
|
| 38 |
-
shall not be hidden and shall be unambiguously available
|
| 39 |
-
BinaryTypeTrait.
|
| 40 |
|
| 41 |
A *TransformationTrait* modifies a property of a type. It shall be a
|
| 42 |
class template that takes one template type argument and, optionally,
|
| 43 |
additional arguments that help define the modification. It shall define
|
| 44 |
a publicly accessible nested type named `type`, which shall be a synonym
|
|
@@ -46,16 +49,19 @@ for the modified type.
|
|
| 46 |
|
| 47 |
### Header `<type_traits>` synopsis <a id="meta.type.synop">[[meta.type.synop]]</a>
|
| 48 |
|
| 49 |
``` cpp
|
| 50 |
namespace std {
|
| 51 |
-
// [meta.help], helper class
|
| 52 |
template <class T, T v> struct integral_constant;
|
| 53 |
-
typedef integral_constant<bool, true> true_type;
|
| 54 |
-
typedef integral_constant<bool, false> false_type;
|
| 55 |
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
template <class T> struct is_void;
|
| 58 |
template <class T> struct is_null_pointer;
|
| 59 |
template <class T> struct is_integral;
|
| 60 |
template <class T> struct is_floating_point;
|
| 61 |
template <class T> struct is_array;
|
|
@@ -67,31 +73,31 @@ namespace std {
|
|
| 67 |
template <class T> struct is_enum;
|
| 68 |
template <class T> struct is_union;
|
| 69 |
template <class T> struct is_class;
|
| 70 |
template <class T> struct is_function;
|
| 71 |
|
| 72 |
-
// [meta.unary.comp], composite type categories
|
| 73 |
template <class T> struct is_reference;
|
| 74 |
template <class T> struct is_arithmetic;
|
| 75 |
template <class T> struct is_fundamental;
|
| 76 |
template <class T> struct is_object;
|
| 77 |
template <class T> struct is_scalar;
|
| 78 |
template <class T> struct is_compound;
|
| 79 |
template <class T> struct is_member_pointer;
|
| 80 |
|
| 81 |
-
// [meta.unary.prop], type properties
|
| 82 |
template <class T> struct is_const;
|
| 83 |
template <class T> struct is_volatile;
|
| 84 |
template <class T> struct is_trivial;
|
| 85 |
template <class T> struct is_trivially_copyable;
|
| 86 |
template <class T> struct is_standard_layout;
|
| 87 |
template <class T> struct is_pod;
|
| 88 |
-
template <class T> struct is_literal_type;
|
| 89 |
template <class T> struct is_empty;
|
| 90 |
template <class T> struct is_polymorphic;
|
| 91 |
template <class T> struct is_abstract;
|
| 92 |
template <class T> struct is_final;
|
|
|
|
| 93 |
|
| 94 |
template <class T> struct is_signed;
|
| 95 |
template <class T> struct is_unsigned;
|
| 96 |
|
| 97 |
template <class T, class... Args> struct is_constructible;
|
|
@@ -101,10 +107,13 @@ namespace std {
|
|
| 101 |
|
| 102 |
template <class T, class U> struct is_assignable;
|
| 103 |
template <class T> struct is_copy_assignable;
|
| 104 |
template <class T> struct is_move_assignable;
|
| 105 |
|
|
|
|
|
|
|
|
|
|
| 106 |
template <class T> struct is_destructible;
|
| 107 |
|
| 108 |
template <class T, class... Args> struct is_trivially_constructible;
|
| 109 |
template <class T> struct is_trivially_default_constructible;
|
| 110 |
template <class T> struct is_trivially_copy_constructible;
|
|
@@ -122,24 +131,36 @@ namespace std {
|
|
| 122 |
|
| 123 |
template <class T, class U> struct is_nothrow_assignable;
|
| 124 |
template <class T> struct is_nothrow_copy_assignable;
|
| 125 |
template <class T> struct is_nothrow_move_assignable;
|
| 126 |
|
|
|
|
|
|
|
|
|
|
| 127 |
template <class T> struct is_nothrow_destructible;
|
|
|
|
| 128 |
template <class T> struct has_virtual_destructor;
|
| 129 |
|
| 130 |
-
|
|
|
|
|
|
|
| 131 |
template <class T> struct alignment_of;
|
| 132 |
template <class T> struct rank;
|
| 133 |
template <class T, unsigned I = 0> struct extent;
|
| 134 |
|
| 135 |
-
// [meta.rel], type relations
|
| 136 |
template <class T, class U> struct is_same;
|
| 137 |
template <class Base, class Derived> struct is_base_of;
|
| 138 |
template <class From, class To> struct is_convertible;
|
| 139 |
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
template <class T> struct remove_const;
|
| 142 |
template <class T> struct remove_volatile;
|
| 143 |
template <class T> struct remove_cv;
|
| 144 |
template <class T> struct add_const;
|
| 145 |
template <class T> struct add_volatile;
|
|
@@ -156,11 +177,11 @@ namespace std {
|
|
| 156 |
template <class T>
|
| 157 |
using add_volatile_t = typename add_volatile<T>::type;
|
| 158 |
template <class T>
|
| 159 |
using add_cv_t = typename add_cv<T>::type;
|
| 160 |
|
| 161 |
-
// [meta.trans.ref], reference modifications
|
| 162 |
template <class T> struct remove_reference;
|
| 163 |
template <class T> struct add_lvalue_reference;
|
| 164 |
template <class T> struct add_rvalue_reference;
|
| 165 |
|
| 166 |
template <class T>
|
|
@@ -168,54 +189,53 @@ namespace std {
|
|
| 168 |
template <class T>
|
| 169 |
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
| 170 |
template <class T>
|
| 171 |
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
|
| 172 |
|
| 173 |
-
// [meta.trans.sign], sign modifications
|
| 174 |
template <class T> struct make_signed;
|
| 175 |
template <class T> struct make_unsigned;
|
| 176 |
|
| 177 |
template <class T>
|
| 178 |
using make_signed_t = typename make_signed<T>::type;
|
| 179 |
template <class T>
|
| 180 |
using make_unsigned_t = typename make_unsigned<T>::type;
|
| 181 |
|
| 182 |
-
// [meta.trans.arr], array modifications
|
| 183 |
template <class T> struct remove_extent;
|
| 184 |
template <class T> struct remove_all_extents;
|
| 185 |
|
| 186 |
template <class T>
|
| 187 |
using remove_extent_t = typename remove_extent<T>::type;
|
| 188 |
template <class T>
|
| 189 |
using remove_all_extents_t = typename remove_all_extents<T>::type;
|
| 190 |
|
| 191 |
-
// [meta.trans.ptr], pointer modifications
|
| 192 |
template <class T> struct remove_pointer;
|
| 193 |
template <class T> struct add_pointer;
|
| 194 |
|
| 195 |
template <class T>
|
| 196 |
using remove_pointer_t = typename remove_pointer<T>::type;
|
| 197 |
template <class T>
|
| 198 |
using add_pointer_t = typename add_pointer<T>::type;
|
| 199 |
|
| 200 |
-
// [meta.trans.other], other transformations
|
| 201 |
-
template <
|
| 202 |
-
|
| 203 |
struct aligned_storage;
|
| 204 |
-
template <
|
| 205 |
template <class T> struct decay;
|
| 206 |
template <bool, class T = void> struct enable_if;
|
| 207 |
template <bool, class T, class F> struct conditional;
|
| 208 |
template <class... T> struct common_type;
|
| 209 |
template <class T> struct underlying_type;
|
| 210 |
-
template <class
|
| 211 |
-
template <class F, class... ArgTypes> class result_of<F(ArgTypes...)>;
|
| 212 |
|
| 213 |
-
template <
|
| 214 |
-
|
| 215 |
using aligned_storage_t = typename aligned_storage<Len, Align>::type;
|
| 216 |
-
template <
|
| 217 |
using aligned_union_t = typename aligned_union<Len, Types...>::type;
|
| 218 |
template <class T>
|
| 219 |
using decay_t = typename decay<T>::type;
|
| 220 |
template <bool b, class T = void>
|
| 221 |
using enable_if_t = typename enable_if<b, T>::type;
|
|
@@ -223,311 +243,683 @@ namespace std {
|
|
| 223 |
using conditional_t = typename conditional<b, T, F>::type;
|
| 224 |
template <class... T>
|
| 225 |
using common_type_t = typename common_type<T...>::type;
|
| 226 |
template <class T>
|
| 227 |
using underlying_type_t = typename underlying_type<T>::type;
|
| 228 |
-
template <class
|
| 229 |
-
using
|
| 230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
```
|
| 232 |
|
| 233 |
-
The behavior of a program that adds specializations for any of the
|
| 234 |
templates defined in this subclause is undefined unless otherwise
|
| 235 |
specified.
|
| 236 |
|
|
|
|
|
|
|
|
|
|
| 237 |
### Helper classes <a id="meta.help">[[meta.help]]</a>
|
| 238 |
|
| 239 |
``` cpp
|
| 240 |
namespace std {
|
| 241 |
template <class T, T v>
|
| 242 |
struct integral_constant {
|
| 243 |
static constexpr T value = v;
|
| 244 |
-
|
| 245 |
-
|
| 246 |
constexpr operator value_type() const noexcept { return value; }
|
| 247 |
constexpr value_type operator()() const noexcept { return value; }
|
| 248 |
};
|
| 249 |
-
typedef integral_constant<bool, true> true_type;
|
| 250 |
-
typedef integral_constant<bool, false> false_type;
|
| 251 |
}
|
| 252 |
```
|
| 253 |
|
| 254 |
-
The class template `integral_constant`
|
| 255 |
-
`true_type` and `false_type` are used
|
| 256 |
-
interface for various type traits.
|
| 257 |
|
| 258 |
### Unary type traits <a id="meta.unary">[[meta.unary]]</a>
|
| 259 |
|
| 260 |
-
This
|
| 261 |
properties of a type at compile time.
|
| 262 |
|
| 263 |
-
Each of these templates shall be a UnaryTypeTrait ([[meta.rqmts]])
|
| 264 |
-
a
|
| 265 |
-
true, otherwise `false_type`.
|
| 266 |
|
| 267 |
#### Primary type categories <a id="meta.unary.cat">[[meta.unary.cat]]</a>
|
| 268 |
|
| 269 |
The primary type categories correspond to the descriptions given in
|
| 270 |
section [[basic.types]] of the C++standard.
|
| 271 |
|
| 272 |
For any given type `T`, the result of applying one of these templates to
|
| 273 |
-
`T` and to
|
| 274 |
|
| 275 |
-
For any given type `T`, exactly one of the primary type
|
| 276 |
-
`value` member that evaluates to `true`.
|
| 277 |
|
| 278 |
#### Composite type traits <a id="meta.unary.comp">[[meta.unary.comp]]</a>
|
| 279 |
|
| 280 |
These templates provide convenient compositions of the primary type
|
| 281 |
categories, corresponding to the descriptions given in section
|
| 282 |
[[basic.types]].
|
| 283 |
|
| 284 |
For any given type `T`, the result of applying one of these templates to
|
| 285 |
-
`T`
|
| 286 |
|
| 287 |
#### Type properties <a id="meta.unary.prop">[[meta.unary.prop]]</a>
|
| 288 |
|
| 289 |
These templates provide access to some of the more important properties
|
| 290 |
of types.
|
| 291 |
|
| 292 |
It is unspecified whether the library defines any full or partial
|
| 293 |
specializations of any of these templates.
|
| 294 |
|
| 295 |
-
For all of the class templates `X` declared in this
|
| 296 |
instantiating that template with a template-argument that is a class
|
| 297 |
template specialization may result in the implicit instantiation of the
|
| 298 |
template argument if and only if the semantics of `X` require that the
|
| 299 |
argument must be a complete type.
|
| 300 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
``` cpp
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
```
|
| 308 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
``` cpp
|
| 310 |
remove_const_t<const volatile int> // volatile int
|
| 311 |
remove_const_t<const int* const> // const int*
|
| 312 |
remove_const_t<const int&> // const int&
|
| 313 |
remove_const_t<const int[3]> // int[3]
|
| 314 |
```
|
| 315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
``` cpp
|
| 317 |
// Given:
|
| 318 |
struct P final { };
|
| 319 |
union U1 { };
|
| 320 |
union U2 final { };
|
| 321 |
|
| 322 |
// the following assertions hold:
|
| 323 |
-
static_assert(!
|
| 324 |
-
static_assert(
|
| 325 |
-
static_assert(!
|
| 326 |
-
static_assert(
|
| 327 |
```
|
| 328 |
|
| 329 |
-
|
| 330 |
|
| 331 |
-
|
| 332 |
-
template <class T>
|
| 333 |
-
add_rvalue_reference_t<T> create() noexcept;
|
| 334 |
-
```
|
| 335 |
-
|
| 336 |
-
the predicate condition for a template specialization
|
| 337 |
`is_constructible<T, Args...>` shall be satisfied if and only if the
|
| 338 |
following variable definition would be well-formed for some invented
|
| 339 |
variable `t`:
|
| 340 |
|
| 341 |
``` cpp
|
| 342 |
-
T t(
|
| 343 |
```
|
| 344 |
|
| 345 |
-
These tokens are never interpreted as a function
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
|
| 354 |
### Type property queries <a id="meta.unary.prop.query">[[meta.unary.prop.query]]</a>
|
| 355 |
|
| 356 |
-
This
|
| 357 |
of types at compile time.
|
| 358 |
|
| 359 |
Each of these templates shall be a `UnaryTypeTrait` ([[meta.rqmts]])
|
| 360 |
-
with a
|
|
|
|
|
|
|
| 361 |
|
| 362 |
``` cpp
|
| 363 |
// the following assertions hold:
|
| 364 |
-
assert(
|
| 365 |
-
assert(
|
| 366 |
-
assert(
|
| 367 |
```
|
| 368 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 369 |
``` cpp
|
| 370 |
// the following assertions hold:
|
| 371 |
-
assert(
|
| 372 |
-
assert(
|
| 373 |
-
assert(
|
| 374 |
-
assert(
|
| 375 |
-
assert((
|
| 376 |
-
assert((
|
| 377 |
-
assert((
|
| 378 |
-
assert((
|
| 379 |
```
|
| 380 |
|
|
|
|
|
|
|
| 381 |
### Relationships between types <a id="meta.rel">[[meta.rel]]</a>
|
| 382 |
|
| 383 |
-
This
|
| 384 |
relationships between types at compile time.
|
| 385 |
|
| 386 |
-
Each of these templates shall be a BinaryTypeTrait ([[meta.rqmts]])
|
| 387 |
-
with a
|
| 388 |
is true, otherwise `false_type`.
|
| 389 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 390 |
``` cpp
|
| 391 |
struct B {};
|
| 392 |
struct B1 : B {};
|
| 393 |
struct B2 : B {};
|
| 394 |
struct D : private B1, private B2 {};
|
| 395 |
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
```
|
| 405 |
|
| 406 |
-
|
| 407 |
|
| 408 |
-
|
| 409 |
-
template <class T>
|
| 410 |
-
add_rvalue_reference_t<T> create() noexcept;
|
| 411 |
-
```
|
| 412 |
-
|
| 413 |
-
the predicate condition for a template specialization
|
| 414 |
`is_convertible<From, To>` shall be satisfied if and only if the return
|
| 415 |
expression in the following code would be well-formed, including any
|
| 416 |
implicit conversions to the return type of the function:
|
| 417 |
|
| 418 |
``` cpp
|
| 419 |
To test() {
|
| 420 |
-
return
|
| 421 |
}
|
| 422 |
```
|
| 423 |
|
| 424 |
-
This requirement gives well defined results for reference
|
| 425 |
-
types, array types, and function types.
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
|
|
|
|
|
|
|
|
|
| 434 |
|
| 435 |
### Transformations between types <a id="meta.trans">[[meta.trans]]</a>
|
| 436 |
|
| 437 |
-
This
|
| 438 |
-
|
| 439 |
|
| 440 |
Each of the templates in this subclause shall be a
|
| 441 |
-
|
| 442 |
|
| 443 |
#### Const-volatile modifications <a id="meta.trans.cv">[[meta.trans.cv]]</a>
|
| 444 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
#### Reference modifications <a id="meta.trans.ref">[[meta.trans.ref]]</a>
|
| 446 |
|
|
|
|
|
|
|
|
|
|
| 447 |
#### Sign modifications <a id="meta.trans.sign">[[meta.trans.sign]]</a>
|
| 448 |
|
| 449 |
#### Array modifications <a id="meta.trans.arr">[[meta.trans.arr]]</a>
|
| 450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 451 |
``` cpp
|
| 452 |
// the following assertions hold:
|
| 453 |
-
assert((
|
| 454 |
-
assert((
|
| 455 |
-
assert((
|
| 456 |
-
assert((
|
| 457 |
```
|
| 458 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 459 |
``` cpp
|
| 460 |
// the following assertions hold:
|
| 461 |
-
assert((
|
| 462 |
-
assert((
|
| 463 |
-
assert((
|
| 464 |
-
assert((
|
| 465 |
```
|
| 466 |
|
|
|
|
|
|
|
| 467 |
#### Pointer modifications <a id="meta.trans.ptr">[[meta.trans.ptr]]</a>
|
| 468 |
|
| 469 |
#### Other transformations <a id="meta.trans.other">[[meta.trans.other]]</a>
|
| 470 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 471 |
A typical implementation would define `aligned_storage` as:
|
| 472 |
|
| 473 |
``` cpp
|
| 474 |
-
template <
|
| 475 |
struct aligned_storage {
|
| 476 |
typedef struct {
|
| 477 |
alignas(Alignment) unsigned char __data[Len];
|
| 478 |
} type;
|
| 479 |
};
|
| 480 |
```
|
| 481 |
|
|
|
|
|
|
|
| 482 |
It is *implementation-defined* whether any extended alignment is
|
| 483 |
supported ([[basic.align]]).
|
| 484 |
|
| 485 |
-
|
|
|
|
|
|
|
| 486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 487 |
``` cpp
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
template <class T>
|
| 491 |
-
struct common_type<T> {
|
| 492 |
-
typedef decay_t<T> type;
|
| 493 |
-
};
|
| 494 |
-
|
| 495 |
-
template <class T, class U>
|
| 496 |
-
struct common_type<T, U> {
|
| 497 |
-
typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type;
|
| 498 |
-
};
|
| 499 |
-
|
| 500 |
-
template <class T, class U, class... V>
|
| 501 |
-
struct common_type<T, U, V...> {
|
| 502 |
-
typedef common_type_t<common_type_t<T, U>, V...> type;
|
| 503 |
-
};
|
| 504 |
```
|
| 505 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
Given these definitions:
|
| 507 |
|
| 508 |
``` cpp
|
| 509 |
-
|
| 510 |
-
|
| 511 |
|
| 512 |
struct S {
|
| 513 |
operator PF2() const;
|
| 514 |
double operator()(char, int&);
|
| 515 |
void fn(long) const;
|
| 516 |
char data;
|
| 517 |
};
|
| 518 |
|
| 519 |
-
|
| 520 |
-
|
| 521 |
```
|
| 522 |
|
| 523 |
the following assertions will hold:
|
| 524 |
|
| 525 |
``` cpp
|
| 526 |
-
static_assert(
|
| 527 |
-
static_assert(
|
| 528 |
-
static_assert(
|
| 529 |
-
static_assert(
|
| 530 |
-
static_assert(
|
| 531 |
-
static_assert(
|
| 532 |
```
|
| 533 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
given type belongs. The type property inspection traits allow important
|
| 11 |
characteristics of types or of combinations of types to be inspected.
|
| 12 |
The type transformations allow certain properties of types to be
|
| 13 |
manipulated.
|
| 14 |
|
| 15 |
+
All functions specified in this subclause are signal-safe (
|
| 16 |
+
[[csignal.syn]]).
|
| 17 |
+
|
| 18 |
### Requirements <a id="meta.rqmts">[[meta.rqmts]]</a>
|
| 19 |
|
| 20 |
A *UnaryTypeTrait* describes a property of a type. It shall be a class
|
| 21 |
template that takes one template type argument and, optionally,
|
| 22 |
additional arguments that help define the property being described. It
|
| 23 |
shall be `DefaultConstructible`, `CopyConstructible`, and publicly and
|
| 24 |
+
unambiguously derived, directly or indirectly, from its *base
|
| 25 |
+
characteristic*, which is a specialization of the template
|
| 26 |
`integral_constant` ([[meta.help]]), with the arguments to the template
|
| 27 |
`integral_constant` determined by the requirements for the particular
|
| 28 |
+
property being described. The member names of the base characteristic
|
| 29 |
shall not be hidden and shall be unambiguously available in the
|
| 30 |
+
`UnaryTypeTrait`.
|
| 31 |
|
| 32 |
A *BinaryTypeTrait* describes a relationship between two types. It shall
|
| 33 |
be a class template that takes two template type arguments and,
|
| 34 |
optionally, additional arguments that help define the relationship being
|
| 35 |
described. It shall be `DefaultConstructible`, `CopyConstructible`, and
|
| 36 |
publicly and unambiguously derived, directly or indirectly, from its
|
| 37 |
+
*base characteristic*, which is a specialization of the template
|
| 38 |
`integral_constant` ([[meta.help]]), with the arguments to the template
|
| 39 |
`integral_constant` determined by the requirements for the particular
|
| 40 |
+
relationship being described. The member names of the base
|
| 41 |
+
characteristic shall not be hidden and shall be unambiguously available
|
| 42 |
+
in the `BinaryTypeTrait`.
|
| 43 |
|
| 44 |
A *TransformationTrait* modifies a property of a type. It shall be a
|
| 45 |
class template that takes one template type argument and, optionally,
|
| 46 |
additional arguments that help define the modification. It shall define
|
| 47 |
a publicly accessible nested type named `type`, which shall be a synonym
|
|
|
|
| 49 |
|
| 50 |
### Header `<type_traits>` synopsis <a id="meta.type.synop">[[meta.type.synop]]</a>
|
| 51 |
|
| 52 |
``` cpp
|
| 53 |
namespace std {
|
| 54 |
+
// [meta.help], helper class
|
| 55 |
template <class T, T v> struct integral_constant;
|
|
|
|
|
|
|
| 56 |
|
| 57 |
+
template <bool B>
|
| 58 |
+
using bool_constant = integral_constant<bool, B>;
|
| 59 |
+
using true_type = bool_constant<true>;
|
| 60 |
+
using false_type = bool_constant<false>;
|
| 61 |
+
|
| 62 |
+
// [meta.unary.cat], primary type categories
|
| 63 |
template <class T> struct is_void;
|
| 64 |
template <class T> struct is_null_pointer;
|
| 65 |
template <class T> struct is_integral;
|
| 66 |
template <class T> struct is_floating_point;
|
| 67 |
template <class T> struct is_array;
|
|
|
|
| 73 |
template <class T> struct is_enum;
|
| 74 |
template <class T> struct is_union;
|
| 75 |
template <class T> struct is_class;
|
| 76 |
template <class T> struct is_function;
|
| 77 |
|
| 78 |
+
// [meta.unary.comp], composite type categories
|
| 79 |
template <class T> struct is_reference;
|
| 80 |
template <class T> struct is_arithmetic;
|
| 81 |
template <class T> struct is_fundamental;
|
| 82 |
template <class T> struct is_object;
|
| 83 |
template <class T> struct is_scalar;
|
| 84 |
template <class T> struct is_compound;
|
| 85 |
template <class T> struct is_member_pointer;
|
| 86 |
|
| 87 |
+
// [meta.unary.prop], type properties
|
| 88 |
template <class T> struct is_const;
|
| 89 |
template <class T> struct is_volatile;
|
| 90 |
template <class T> struct is_trivial;
|
| 91 |
template <class T> struct is_trivially_copyable;
|
| 92 |
template <class T> struct is_standard_layout;
|
| 93 |
template <class T> struct is_pod;
|
|
|
|
| 94 |
template <class T> struct is_empty;
|
| 95 |
template <class T> struct is_polymorphic;
|
| 96 |
template <class T> struct is_abstract;
|
| 97 |
template <class T> struct is_final;
|
| 98 |
+
template <class T> struct is_aggregate;
|
| 99 |
|
| 100 |
template <class T> struct is_signed;
|
| 101 |
template <class T> struct is_unsigned;
|
| 102 |
|
| 103 |
template <class T, class... Args> struct is_constructible;
|
|
|
|
| 107 |
|
| 108 |
template <class T, class U> struct is_assignable;
|
| 109 |
template <class T> struct is_copy_assignable;
|
| 110 |
template <class T> struct is_move_assignable;
|
| 111 |
|
| 112 |
+
template <class T, class U> struct is_swappable_with;
|
| 113 |
+
template <class T> struct is_swappable;
|
| 114 |
+
|
| 115 |
template <class T> struct is_destructible;
|
| 116 |
|
| 117 |
template <class T, class... Args> struct is_trivially_constructible;
|
| 118 |
template <class T> struct is_trivially_default_constructible;
|
| 119 |
template <class T> struct is_trivially_copy_constructible;
|
|
|
|
| 131 |
|
| 132 |
template <class T, class U> struct is_nothrow_assignable;
|
| 133 |
template <class T> struct is_nothrow_copy_assignable;
|
| 134 |
template <class T> struct is_nothrow_move_assignable;
|
| 135 |
|
| 136 |
+
template <class T, class U> struct is_nothrow_swappable_with;
|
| 137 |
+
template <class T> struct is_nothrow_swappable;
|
| 138 |
+
|
| 139 |
template <class T> struct is_nothrow_destructible;
|
| 140 |
+
|
| 141 |
template <class T> struct has_virtual_destructor;
|
| 142 |
|
| 143 |
+
template <class T> struct has_unique_object_representations;
|
| 144 |
+
|
| 145 |
+
// [meta.unary.prop.query], type property queries
|
| 146 |
template <class T> struct alignment_of;
|
| 147 |
template <class T> struct rank;
|
| 148 |
template <class T, unsigned I = 0> struct extent;
|
| 149 |
|
| 150 |
+
// [meta.rel], type relations
|
| 151 |
template <class T, class U> struct is_same;
|
| 152 |
template <class Base, class Derived> struct is_base_of;
|
| 153 |
template <class From, class To> struct is_convertible;
|
| 154 |
|
| 155 |
+
template <class Fn, class... ArgTypes> struct is_invocable;
|
| 156 |
+
template <class R, class Fn, class... ArgTypes> struct is_invocable_r;
|
| 157 |
+
|
| 158 |
+
template <class Fn, class... ArgTypes> struct is_nothrow_invocable;
|
| 159 |
+
template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;
|
| 160 |
+
|
| 161 |
+
// [meta.trans.cv], const-volatile modifications
|
| 162 |
template <class T> struct remove_const;
|
| 163 |
template <class T> struct remove_volatile;
|
| 164 |
template <class T> struct remove_cv;
|
| 165 |
template <class T> struct add_const;
|
| 166 |
template <class T> struct add_volatile;
|
|
|
|
| 177 |
template <class T>
|
| 178 |
using add_volatile_t = typename add_volatile<T>::type;
|
| 179 |
template <class T>
|
| 180 |
using add_cv_t = typename add_cv<T>::type;
|
| 181 |
|
| 182 |
+
// [meta.trans.ref], reference modifications
|
| 183 |
template <class T> struct remove_reference;
|
| 184 |
template <class T> struct add_lvalue_reference;
|
| 185 |
template <class T> struct add_rvalue_reference;
|
| 186 |
|
| 187 |
template <class T>
|
|
|
|
| 189 |
template <class T>
|
| 190 |
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
| 191 |
template <class T>
|
| 192 |
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
|
| 193 |
|
| 194 |
+
// [meta.trans.sign], sign modifications
|
| 195 |
template <class T> struct make_signed;
|
| 196 |
template <class T> struct make_unsigned;
|
| 197 |
|
| 198 |
template <class T>
|
| 199 |
using make_signed_t = typename make_signed<T>::type;
|
| 200 |
template <class T>
|
| 201 |
using make_unsigned_t = typename make_unsigned<T>::type;
|
| 202 |
|
| 203 |
+
// [meta.trans.arr], array modifications
|
| 204 |
template <class T> struct remove_extent;
|
| 205 |
template <class T> struct remove_all_extents;
|
| 206 |
|
| 207 |
template <class T>
|
| 208 |
using remove_extent_t = typename remove_extent<T>::type;
|
| 209 |
template <class T>
|
| 210 |
using remove_all_extents_t = typename remove_all_extents<T>::type;
|
| 211 |
|
| 212 |
+
// [meta.trans.ptr], pointer modifications
|
| 213 |
template <class T> struct remove_pointer;
|
| 214 |
template <class T> struct add_pointer;
|
| 215 |
|
| 216 |
template <class T>
|
| 217 |
using remove_pointer_t = typename remove_pointer<T>::type;
|
| 218 |
template <class T>
|
| 219 |
using add_pointer_t = typename add_pointer<T>::type;
|
| 220 |
|
| 221 |
+
// [meta.trans.other], other transformations
|
| 222 |
+
template <size_t Len,
|
| 223 |
+
size_t Align = default-alignment> // see [meta.trans.other]
|
| 224 |
struct aligned_storage;
|
| 225 |
+
template <size_t Len, class... Types> struct aligned_union;
|
| 226 |
template <class T> struct decay;
|
| 227 |
template <bool, class T = void> struct enable_if;
|
| 228 |
template <bool, class T, class F> struct conditional;
|
| 229 |
template <class... T> struct common_type;
|
| 230 |
template <class T> struct underlying_type;
|
| 231 |
+
template <class Fn, class... ArgTypes> struct invoke_result;
|
|
|
|
| 232 |
|
| 233 |
+
template <size_t Len,
|
| 234 |
+
size_t Align = default-alignment> // see [meta.trans.other]
|
| 235 |
using aligned_storage_t = typename aligned_storage<Len, Align>::type;
|
| 236 |
+
template <size_t Len, class... Types>
|
| 237 |
using aligned_union_t = typename aligned_union<Len, Types...>::type;
|
| 238 |
template <class T>
|
| 239 |
using decay_t = typename decay<T>::type;
|
| 240 |
template <bool b, class T = void>
|
| 241 |
using enable_if_t = typename enable_if<b, T>::type;
|
|
|
|
| 243 |
using conditional_t = typename conditional<b, T, F>::type;
|
| 244 |
template <class... T>
|
| 245 |
using common_type_t = typename common_type<T...>::type;
|
| 246 |
template <class T>
|
| 247 |
using underlying_type_t = typename underlying_type<T>::type;
|
| 248 |
+
template <class Fn, class... ArgTypes>
|
| 249 |
+
using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type;
|
| 250 |
+
template <class...>
|
| 251 |
+
using void_t = void;
|
| 252 |
+
|
| 253 |
+
// [meta.logical], logical operator traits
|
| 254 |
+
template<class... B> struct conjunction;
|
| 255 |
+
template<class... B> struct disjunction;
|
| 256 |
+
template<class B> struct negation;
|
| 257 |
+
|
| 258 |
+
// [meta.unary.cat], primary type categories
|
| 259 |
+
template <class T> inline constexpr bool is_void_v
|
| 260 |
+
= is_void<T>::value;
|
| 261 |
+
template <class T> inline constexpr bool is_null_pointer_v
|
| 262 |
+
= is_null_pointer<T>::value;
|
| 263 |
+
template <class T> inline constexpr bool is_integral_v
|
| 264 |
+
= is_integral<T>::value;
|
| 265 |
+
template <class T> inline constexpr bool is_floating_point_v
|
| 266 |
+
= is_floating_point<T>::value;
|
| 267 |
+
template <class T> inline constexpr bool is_array_v
|
| 268 |
+
= is_array<T>::value;
|
| 269 |
+
template <class T> inline constexpr bool is_pointer_v
|
| 270 |
+
= is_pointer<T>::value;
|
| 271 |
+
template <class T> inline constexpr bool is_lvalue_reference_v
|
| 272 |
+
= is_lvalue_reference<T>::value;
|
| 273 |
+
template <class T> inline constexpr bool is_rvalue_reference_v
|
| 274 |
+
= is_rvalue_reference<T>::value;
|
| 275 |
+
template <class T> inline constexpr bool is_member_object_pointer_v
|
| 276 |
+
= is_member_object_pointer<T>::value;
|
| 277 |
+
template <class T> inline constexpr bool is_member_function_pointer_v
|
| 278 |
+
= is_member_function_pointer<T>::value;
|
| 279 |
+
template <class T> inline constexpr bool is_enum_v
|
| 280 |
+
= is_enum<T>::value;
|
| 281 |
+
template <class T> inline constexpr bool is_union_v
|
| 282 |
+
= is_union<T>::value;
|
| 283 |
+
template <class T> inline constexpr bool is_class_v
|
| 284 |
+
= is_class<T>::value;
|
| 285 |
+
template <class T> inline constexpr bool is_function_v
|
| 286 |
+
= is_function<T>::value;
|
| 287 |
+
|
| 288 |
+
// [meta.unary.comp], composite type categories
|
| 289 |
+
template <class T> inline constexpr bool is_reference_v
|
| 290 |
+
= is_reference<T>::value;
|
| 291 |
+
template <class T> inline constexpr bool is_arithmetic_v
|
| 292 |
+
= is_arithmetic<T>::value;
|
| 293 |
+
template <class T> inline constexpr bool is_fundamental_v
|
| 294 |
+
= is_fundamental<T>::value;
|
| 295 |
+
template <class T> inline constexpr bool is_object_v
|
| 296 |
+
= is_object<T>::value;
|
| 297 |
+
template <class T> inline constexpr bool is_scalar_v
|
| 298 |
+
= is_scalar<T>::value;
|
| 299 |
+
template <class T> inline constexpr bool is_compound_v
|
| 300 |
+
= is_compound<T>::value;
|
| 301 |
+
template <class T> inline constexpr bool is_member_pointer_v
|
| 302 |
+
= is_member_pointer<T>::value;
|
| 303 |
+
|
| 304 |
+
// [meta.unary.prop], type properties
|
| 305 |
+
template <class T> inline constexpr bool is_const_v
|
| 306 |
+
= is_const<T>::value;
|
| 307 |
+
template <class T> inline constexpr bool is_volatile_v
|
| 308 |
+
= is_volatile<T>::value;
|
| 309 |
+
template <class T> inline constexpr bool is_trivial_v
|
| 310 |
+
= is_trivial<T>::value;
|
| 311 |
+
template <class T> inline constexpr bool is_trivially_copyable_v
|
| 312 |
+
= is_trivially_copyable<T>::value;
|
| 313 |
+
template <class T> inline constexpr bool is_standard_layout_v
|
| 314 |
+
= is_standard_layout<T>::value;
|
| 315 |
+
template <class T> inline constexpr bool is_pod_v
|
| 316 |
+
= is_pod<T>::value;
|
| 317 |
+
template <class T> inline constexpr bool is_empty_v
|
| 318 |
+
= is_empty<T>::value;
|
| 319 |
+
template <class T> inline constexpr bool is_polymorphic_v
|
| 320 |
+
= is_polymorphic<T>::value;
|
| 321 |
+
template <class T> inline constexpr bool is_abstract_v
|
| 322 |
+
= is_abstract<T>::value;
|
| 323 |
+
template <class T> inline constexpr bool is_final_v
|
| 324 |
+
= is_final<T>::value;
|
| 325 |
+
template <class T> inline constexpr bool is_aggregate_v
|
| 326 |
+
= is_aggregate<T>::value;
|
| 327 |
+
template <class T> inline constexpr bool is_signed_v
|
| 328 |
+
= is_signed<T>::value;
|
| 329 |
+
template <class T> inline constexpr bool is_unsigned_v
|
| 330 |
+
= is_unsigned<T>::value;
|
| 331 |
+
template <class T, class... Args> inline constexpr bool is_constructible_v
|
| 332 |
+
= is_constructible<T, Args...>::value;
|
| 333 |
+
template <class T> inline constexpr bool is_default_constructible_v
|
| 334 |
+
= is_default_constructible<T>::value;
|
| 335 |
+
template <class T> inline constexpr bool is_copy_constructible_v
|
| 336 |
+
= is_copy_constructible<T>::value;
|
| 337 |
+
template <class T> inline constexpr bool is_move_constructible_v
|
| 338 |
+
= is_move_constructible<T>::value;
|
| 339 |
+
template <class T, class U> inline constexpr bool is_assignable_v
|
| 340 |
+
= is_assignable<T, U>::value;
|
| 341 |
+
template <class T> inline constexpr bool is_copy_assignable_v
|
| 342 |
+
= is_copy_assignable<T>::value;
|
| 343 |
+
template <class T> inline constexpr bool is_move_assignable_v
|
| 344 |
+
= is_move_assignable<T>::value;
|
| 345 |
+
template <class T, class U> inline constexpr bool is_swappable_with_v
|
| 346 |
+
= is_swappable_with<T, U>::value;
|
| 347 |
+
template <class T> inline constexpr bool is_swappable_v
|
| 348 |
+
= is_swappable<T>::value;
|
| 349 |
+
template <class T> inline constexpr bool is_destructible_v
|
| 350 |
+
= is_destructible<T>::value;
|
| 351 |
+
template <class T, class... Args> inline constexpr bool is_trivially_constructible_v
|
| 352 |
+
= is_trivially_constructible<T, Args...>::value;
|
| 353 |
+
template <class T> inline constexpr bool is_trivially_default_constructible_v
|
| 354 |
+
= is_trivially_default_constructible<T>::value;
|
| 355 |
+
template <class T> inline constexpr bool is_trivially_copy_constructible_v
|
| 356 |
+
= is_trivially_copy_constructible<T>::value;
|
| 357 |
+
template <class T> inline constexpr bool is_trivially_move_constructible_v
|
| 358 |
+
= is_trivially_move_constructible<T>::value;
|
| 359 |
+
template <class T, class U> inline constexpr bool is_trivially_assignable_v
|
| 360 |
+
= is_trivially_assignable<T, U>::value;
|
| 361 |
+
template <class T> inline constexpr bool is_trivially_copy_assignable_v
|
| 362 |
+
= is_trivially_copy_assignable<T>::value;
|
| 363 |
+
template <class T> inline constexpr bool is_trivially_move_assignable_v
|
| 364 |
+
= is_trivially_move_assignable<T>::value;
|
| 365 |
+
template <class T> inline constexpr bool is_trivially_destructible_v
|
| 366 |
+
= is_trivially_destructible<T>::value;
|
| 367 |
+
template <class T, class... Args> inline constexpr bool is_nothrow_constructible_v
|
| 368 |
+
= is_nothrow_constructible<T, Args...>::value;
|
| 369 |
+
template <class T> inline constexpr bool is_nothrow_default_constructible_v
|
| 370 |
+
= is_nothrow_default_constructible<T>::value;
|
| 371 |
+
template <class T> inline constexpr bool is_nothrow_copy_constructible_v
|
| 372 |
+
= is_nothrow_copy_constructible<T>::value;
|
| 373 |
+
template <class T> inline constexpr bool is_nothrow_move_constructible_v
|
| 374 |
+
= is_nothrow_move_constructible<T>::value;
|
| 375 |
+
template <class T, class U> inline constexpr bool is_nothrow_assignable_v
|
| 376 |
+
= is_nothrow_assignable<T, U>::value;
|
| 377 |
+
template <class T> inline constexpr bool is_nothrow_copy_assignable_v
|
| 378 |
+
= is_nothrow_copy_assignable<T>::value;
|
| 379 |
+
template <class T> inline constexpr bool is_nothrow_move_assignable_v
|
| 380 |
+
= is_nothrow_move_assignable<T>::value;
|
| 381 |
+
template <class T, class U> inline constexpr bool is_nothrow_swappable_with_v
|
| 382 |
+
= is_nothrow_swappable_with<T, U>::value;
|
| 383 |
+
template <class T> inline constexpr bool is_nothrow_swappable_v
|
| 384 |
+
= is_nothrow_swappable<T>::value;
|
| 385 |
+
template <class T> inline constexpr bool is_nothrow_destructible_v
|
| 386 |
+
= is_nothrow_destructible<T>::value;
|
| 387 |
+
template <class T> inline constexpr bool has_virtual_destructor_v
|
| 388 |
+
= has_virtual_destructor<T>::value;
|
| 389 |
+
template <class T> inline constexpr bool has_unique_object_representations_v
|
| 390 |
+
= has_unique_object_representations<T>::value;
|
| 391 |
+
|
| 392 |
+
// [meta.unary.prop.query], type property queries
|
| 393 |
+
template <class T> inline constexpr size_t alignment_of_v
|
| 394 |
+
= alignment_of<T>::value;
|
| 395 |
+
template <class T> inline constexpr size_t rank_v
|
| 396 |
+
= rank<T>::value;
|
| 397 |
+
template <class T, unsigned I = 0> inline constexpr size_t extent_v
|
| 398 |
+
= extent<T, I>::value;
|
| 399 |
+
|
| 400 |
+
// [meta.rel], type relations
|
| 401 |
+
template <class T, class U> inline constexpr bool is_same_v
|
| 402 |
+
= is_same<T, U>::value;
|
| 403 |
+
template <class Base, class Derived> inline constexpr bool is_base_of_v
|
| 404 |
+
= is_base_of<Base, Derived>::value;
|
| 405 |
+
template <class From, class To> inline constexpr bool is_convertible_v
|
| 406 |
+
= is_convertible<From, To>::value;
|
| 407 |
+
template <class Fn, class... ArgTypes> inline constexpr bool is_invocable_v
|
| 408 |
+
= is_invocable<Fn, ArgTypes...>::value;
|
| 409 |
+
template <class R, class Fn, class... ArgTypes> inline constexpr bool is_invocable_r_v
|
| 410 |
+
= is_invocable_r<R, Fn, ArgTypes...>::value;
|
| 411 |
+
template <class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_v
|
| 412 |
+
= is_nothrow_invocable<Fn, ArgTypes...>::value;
|
| 413 |
+
template <class R, class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_r_v
|
| 414 |
+
= is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;
|
| 415 |
+
|
| 416 |
+
// [meta.logical], logical operator traits
|
| 417 |
+
template<class... B> inline constexpr bool conjunction_v = conjunction<B...>::value;
|
| 418 |
+
template<class... B> inline constexpr bool disjunction_v = disjunction<B...>::value;
|
| 419 |
+
template<class B> inline constexpr bool negation_v = negation<B>::value;
|
| 420 |
+
}
|
| 421 |
```
|
| 422 |
|
| 423 |
+
The behavior of a program that adds specializations for any of the
|
| 424 |
templates defined in this subclause is undefined unless otherwise
|
| 425 |
specified.
|
| 426 |
|
| 427 |
+
Unless otherwise specified, an incomplete type may be used to
|
| 428 |
+
instantiate a template in this subclause.
|
| 429 |
+
|
| 430 |
### Helper classes <a id="meta.help">[[meta.help]]</a>
|
| 431 |
|
| 432 |
``` cpp
|
| 433 |
namespace std {
|
| 434 |
template <class T, T v>
|
| 435 |
struct integral_constant {
|
| 436 |
static constexpr T value = v;
|
| 437 |
+
using value_type = T;
|
| 438 |
+
using type = integral_constant<T, v>;
|
| 439 |
constexpr operator value_type() const noexcept { return value; }
|
| 440 |
constexpr value_type operator()() const noexcept { return value; }
|
| 441 |
};
|
|
|
|
|
|
|
| 442 |
}
|
| 443 |
```
|
| 444 |
|
| 445 |
+
The class template `integral_constant`, alias template `bool_constant`,
|
| 446 |
+
and its associated *typedef-name*s `true_type` and `false_type` are used
|
| 447 |
+
as base classes to define the interface for various type traits.
|
| 448 |
|
| 449 |
### Unary type traits <a id="meta.unary">[[meta.unary]]</a>
|
| 450 |
|
| 451 |
+
This subclause contains templates that may be used to query the
|
| 452 |
properties of a type at compile time.
|
| 453 |
|
| 454 |
+
Each of these templates shall be a `UnaryTypeTrait` ([[meta.rqmts]])
|
| 455 |
+
with a base characteristic of `true_type` if the corresponding condition
|
| 456 |
+
is `true`, otherwise `false_type`.
|
| 457 |
|
| 458 |
#### Primary type categories <a id="meta.unary.cat">[[meta.unary.cat]]</a>
|
| 459 |
|
| 460 |
The primary type categories correspond to the descriptions given in
|
| 461 |
section [[basic.types]] of the C++standard.
|
| 462 |
|
| 463 |
For any given type `T`, the result of applying one of these templates to
|
| 464 |
+
`T` and to cv `T` shall yield the same result.
|
| 465 |
|
| 466 |
+
[*Note 1*: For any given type `T`, exactly one of the primary type
|
| 467 |
+
categories has a `value` member that evaluates to `true`. — *end note*]
|
| 468 |
|
| 469 |
#### Composite type traits <a id="meta.unary.comp">[[meta.unary.comp]]</a>
|
| 470 |
|
| 471 |
These templates provide convenient compositions of the primary type
|
| 472 |
categories, corresponding to the descriptions given in section
|
| 473 |
[[basic.types]].
|
| 474 |
|
| 475 |
For any given type `T`, the result of applying one of these templates to
|
| 476 |
+
`T` and to cv `T` shall yield the same result.
|
| 477 |
|
| 478 |
#### Type properties <a id="meta.unary.prop">[[meta.unary.prop]]</a>
|
| 479 |
|
| 480 |
These templates provide access to some of the more important properties
|
| 481 |
of types.
|
| 482 |
|
| 483 |
It is unspecified whether the library defines any full or partial
|
| 484 |
specializations of any of these templates.
|
| 485 |
|
| 486 |
+
For all of the class templates `X` declared in this subclause,
|
| 487 |
instantiating that template with a template-argument that is a class
|
| 488 |
template specialization may result in the implicit instantiation of the
|
| 489 |
template argument if and only if the semantics of `X` require that the
|
| 490 |
argument must be a complete type.
|
| 491 |
|
| 492 |
+
For the purpose of defining the templates in this subclause, a function
|
| 493 |
+
call expression `declval<T>()` for any type `T` is considered to be a
|
| 494 |
+
trivial ([[basic.types]], [[special]]) function call that is not an
|
| 495 |
+
odr-use ([[basic.def.odr]]) of `declval` in the context of the
|
| 496 |
+
corresponding definition notwithstanding the restrictions of
|
| 497 |
+
[[declval]].
|
| 498 |
+
|
| 499 |
+
[*Note 1*: A union is a class type that can be marked with
|
| 500 |
+
`final`. — *end note*]
|
| 501 |
+
|
| 502 |
+
[*Example 1*:
|
| 503 |
+
|
| 504 |
``` cpp
|
| 505 |
+
is_const_v<const volatile int> // true
|
| 506 |
+
is_const_v<const int*> // false
|
| 507 |
+
is_const_v<const int&> // false
|
| 508 |
+
is_const_v<int[3]> // false
|
| 509 |
+
is_const_v<const int[3]> // true
|
| 510 |
```
|
| 511 |
|
| 512 |
+
— *end example*]
|
| 513 |
+
|
| 514 |
+
[*Example 2*:
|
| 515 |
+
|
| 516 |
``` cpp
|
| 517 |
remove_const_t<const volatile int> // volatile int
|
| 518 |
remove_const_t<const int* const> // const int*
|
| 519 |
remove_const_t<const int&> // const int&
|
| 520 |
remove_const_t<const int[3]> // int[3]
|
| 521 |
```
|
| 522 |
|
| 523 |
+
— *end example*]
|
| 524 |
+
|
| 525 |
+
[*Example 3*:
|
| 526 |
+
|
| 527 |
``` cpp
|
| 528 |
// Given:
|
| 529 |
struct P final { };
|
| 530 |
union U1 { };
|
| 531 |
union U2 final { };
|
| 532 |
|
| 533 |
// the following assertions hold:
|
| 534 |
+
static_assert(!is_final_v<int>);
|
| 535 |
+
static_assert(is_final_v<P>);
|
| 536 |
+
static_assert(!is_final_v<U1>);
|
| 537 |
+
static_assert(is_final_v<U2>);
|
| 538 |
```
|
| 539 |
|
| 540 |
+
— *end example*]
|
| 541 |
|
| 542 |
+
The predicate condition for a template specialization
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 543 |
`is_constructible<T, Args...>` shall be satisfied if and only if the
|
| 544 |
following variable definition would be well-formed for some invented
|
| 545 |
variable `t`:
|
| 546 |
|
| 547 |
``` cpp
|
| 548 |
+
T t(declval<Args>()...);
|
| 549 |
```
|
| 550 |
|
| 551 |
+
[*Note 2*: These tokens are never interpreted as a function
|
| 552 |
+
declaration. — *end note*]
|
| 553 |
+
|
| 554 |
+
Access checking is performed as if in a context unrelated to `T` and any
|
| 555 |
+
of the `Args`. Only the validity of the immediate context of the
|
| 556 |
+
variable initialization is considered.
|
| 557 |
+
|
| 558 |
+
[*Note 3*: The evaluation of the initialization can result in side
|
| 559 |
+
effects such as the instantiation of class template specializations and
|
| 560 |
+
function template specializations, the generation of implicitly-defined
|
| 561 |
+
functions, and so on. Such side effects are not in the “immediate
|
| 562 |
+
context” and can result in the program being ill-formed. — *end note*]
|
| 563 |
+
|
| 564 |
+
The predicate condition for a template specialization
|
| 565 |
+
`has_unique_object_representations<T>` shall be satisfied if and only
|
| 566 |
+
if:
|
| 567 |
+
|
| 568 |
+
- `T` is trivially copyable, and
|
| 569 |
+
- any two objects of type `T` with the same value have the same object
|
| 570 |
+
representation, where two objects of array or non-union class type are
|
| 571 |
+
considered to have the same value if their respective sequences of
|
| 572 |
+
direct subobjects have the same values, and two objects of union type
|
| 573 |
+
are considered to have the same value if they have the same active
|
| 574 |
+
member and the corresponding members have the same value.
|
| 575 |
+
|
| 576 |
+
The set of scalar types for which this condition holds is
|
| 577 |
+
*implementation-defined*.
|
| 578 |
+
|
| 579 |
+
[*Note 4*: If a type has padding bits, the condition does not hold;
|
| 580 |
+
otherwise, the condition holds true for unsigned integral
|
| 581 |
+
types. — *end note*]
|
| 582 |
|
| 583 |
### Type property queries <a id="meta.unary.prop.query">[[meta.unary.prop.query]]</a>
|
| 584 |
|
| 585 |
+
This subclause contains templates that may be used to query properties
|
| 586 |
of types at compile time.
|
| 587 |
|
| 588 |
Each of these templates shall be a `UnaryTypeTrait` ([[meta.rqmts]])
|
| 589 |
+
with a base characteristic of `integral_constant<size_t, Value>`.
|
| 590 |
+
|
| 591 |
+
[*Example 1*:
|
| 592 |
|
| 593 |
``` cpp
|
| 594 |
// the following assertions hold:
|
| 595 |
+
assert(rank_v<int> == 0);
|
| 596 |
+
assert(rank_v<int[2]> == 1);
|
| 597 |
+
assert(rank_v<int[][4]> == 2);
|
| 598 |
```
|
| 599 |
|
| 600 |
+
— *end example*]
|
| 601 |
+
|
| 602 |
+
[*Example 2*:
|
| 603 |
+
|
| 604 |
``` cpp
|
| 605 |
// the following assertions hold:
|
| 606 |
+
assert(extent_v<int> == 0);
|
| 607 |
+
assert(extent_v<int[2]> == 2);
|
| 608 |
+
assert(extent_v<int[2][4]> == 2);
|
| 609 |
+
assert(extent_v<int[][4]> == 0);
|
| 610 |
+
assert((extent_v<int, 1>) == 0);
|
| 611 |
+
assert((extent_v<int[2], 1>) == 0);
|
| 612 |
+
assert((extent_v<int[2][4], 1>) == 4);
|
| 613 |
+
assert((extent_v<int[][4], 1>) == 4);
|
| 614 |
```
|
| 615 |
|
| 616 |
+
— *end example*]
|
| 617 |
+
|
| 618 |
### Relationships between types <a id="meta.rel">[[meta.rel]]</a>
|
| 619 |
|
| 620 |
+
This subclause contains templates that may be used to query
|
| 621 |
relationships between types at compile time.
|
| 622 |
|
| 623 |
+
Each of these templates shall be a `BinaryTypeTrait` ([[meta.rqmts]])
|
| 624 |
+
with a base characteristic of `true_type` if the corresponding condition
|
| 625 |
is true, otherwise `false_type`.
|
| 626 |
|
| 627 |
+
[*Note 1*: Base classes that are private, protected, or ambiguous are,
|
| 628 |
+
nonetheless, base classes. — *end note*]
|
| 629 |
+
|
| 630 |
+
For the purpose of defining the templates in this subclause, a function
|
| 631 |
+
call expression `declval<T>()` for any type `T` is considered to be a
|
| 632 |
+
trivial ([[basic.types]], [[special]]) function call that is not an
|
| 633 |
+
odr-use ([[basic.def.odr]]) of `declval` in the context of the
|
| 634 |
+
corresponding definition notwithstanding the restrictions of
|
| 635 |
+
[[declval]].
|
| 636 |
+
|
| 637 |
+
[*Example 1*:
|
| 638 |
+
|
| 639 |
``` cpp
|
| 640 |
struct B {};
|
| 641 |
struct B1 : B {};
|
| 642 |
struct B2 : B {};
|
| 643 |
struct D : private B1, private B2 {};
|
| 644 |
|
| 645 |
+
is_base_of_v<B, D> // true
|
| 646 |
+
is_base_of_v<const B, D> // true
|
| 647 |
+
is_base_of_v<B, const D> // true
|
| 648 |
+
is_base_of_v<B, const B> // true
|
| 649 |
+
is_base_of_v<D, B> // false
|
| 650 |
+
is_base_of_v<B&, D&> // false
|
| 651 |
+
is_base_of_v<B[3], D[3]> // false
|
| 652 |
+
is_base_of_v<int, int> // false
|
| 653 |
```
|
| 654 |
|
| 655 |
+
— *end example*]
|
| 656 |
|
| 657 |
+
The predicate condition for a template specialization
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 658 |
`is_convertible<From, To>` shall be satisfied if and only if the return
|
| 659 |
expression in the following code would be well-formed, including any
|
| 660 |
implicit conversions to the return type of the function:
|
| 661 |
|
| 662 |
``` cpp
|
| 663 |
To test() {
|
| 664 |
+
return declval<From>();
|
| 665 |
}
|
| 666 |
```
|
| 667 |
|
| 668 |
+
[*Note 2*: This requirement gives well defined results for reference
|
| 669 |
+
types, void types, array types, and function types. — *end note*]
|
| 670 |
+
|
| 671 |
+
Access checking is performed in a context unrelated to `To` and `From`.
|
| 672 |
+
Only the validity of the immediate context of the *expression* of the
|
| 673 |
+
`return` statement (including initialization of the returned object or
|
| 674 |
+
reference) is considered.
|
| 675 |
+
|
| 676 |
+
[*Note 3*: The initialization can result in side effects such as the
|
| 677 |
+
instantiation of class template specializations and function template
|
| 678 |
+
specializations, the generation of implicitly-defined functions, and so
|
| 679 |
+
on. Such side effects are not in the “immediate context” and can result
|
| 680 |
+
in the program being ill-formed. — *end note*]
|
| 681 |
|
| 682 |
### Transformations between types <a id="meta.trans">[[meta.trans]]</a>
|
| 683 |
|
| 684 |
+
This subclause contains templates that may be used to transform one type
|
| 685 |
+
to another following some predefined rule.
|
| 686 |
|
| 687 |
Each of the templates in this subclause shall be a
|
| 688 |
+
`TransformationTrait` ([[meta.rqmts]]).
|
| 689 |
|
| 690 |
#### Const-volatile modifications <a id="meta.trans.cv">[[meta.trans.cv]]</a>
|
| 691 |
|
| 692 |
+
[*Example 1*: `remove_const_t<const volatile int>` evaluates to
|
| 693 |
+
`volatile int`, whereas `remove_const_t<const int*>` evaluates to
|
| 694 |
+
`const int*`. — *end example*]
|
| 695 |
+
|
| 696 |
#### Reference modifications <a id="meta.trans.ref">[[meta.trans.ref]]</a>
|
| 697 |
|
| 698 |
+
[*Note 1*: This rule reflects the semantics of reference collapsing (
|
| 699 |
+
[[dcl.ref]]). — *end note*]
|
| 700 |
+
|
| 701 |
#### Sign modifications <a id="meta.trans.sign">[[meta.trans.sign]]</a>
|
| 702 |
|
| 703 |
#### Array modifications <a id="meta.trans.arr">[[meta.trans.arr]]</a>
|
| 704 |
|
| 705 |
+
[*Note 1*: For multidimensional arrays, only the first array dimension
|
| 706 |
+
is removed. For a type “array of `const U`”, the resulting type is
|
| 707 |
+
`const U`. — *end note*]
|
| 708 |
+
|
| 709 |
+
[*Example 1*:
|
| 710 |
+
|
| 711 |
``` cpp
|
| 712 |
// the following assertions hold:
|
| 713 |
+
assert((is_same_v<remove_extent_t<int>, int>));
|
| 714 |
+
assert((is_same_v<remove_extent_t<int[2]>, int>));
|
| 715 |
+
assert((is_same_v<remove_extent_t<int[2][3]>, int[3]>));
|
| 716 |
+
assert((is_same_v<remove_extent_t<int[][3]>, int[3]>));
|
| 717 |
```
|
| 718 |
|
| 719 |
+
— *end example*]
|
| 720 |
+
|
| 721 |
+
[*Example 2*:
|
| 722 |
+
|
| 723 |
``` cpp
|
| 724 |
// the following assertions hold:
|
| 725 |
+
assert((is_same_v<remove_all_extents_t<int>, int>));
|
| 726 |
+
assert((is_same_v<remove_all_extents_t<int[2]>, int>));
|
| 727 |
+
assert((is_same_v<remove_all_extents_t<int[2][3]>, int>));
|
| 728 |
+
assert((is_same_v<remove_all_extents_t<int[][3]>, int>));
|
| 729 |
```
|
| 730 |
|
| 731 |
+
— *end example*]
|
| 732 |
+
|
| 733 |
#### Pointer modifications <a id="meta.trans.ptr">[[meta.trans.ptr]]</a>
|
| 734 |
|
| 735 |
#### Other transformations <a id="meta.trans.other">[[meta.trans.other]]</a>
|
| 736 |
|
| 737 |
+
[*Note 1*: This behavior is similar to the lvalue-to-rvalue (
|
| 738 |
+
[[conv.lval]]), array-to-pointer ([[conv.array]]), and
|
| 739 |
+
function-to-pointer ([[conv.func]]) conversions applied when an lvalue
|
| 740 |
+
expression is used as an rvalue, but also strips cv-qualifiers from
|
| 741 |
+
class types in order to more closely model by-value argument
|
| 742 |
+
passing. — *end note*]
|
| 743 |
+
|
| 744 |
+
[*Note 2*:
|
| 745 |
+
|
| 746 |
A typical implementation would define `aligned_storage` as:
|
| 747 |
|
| 748 |
``` cpp
|
| 749 |
+
template <size_t Len, size_t Alignment>
|
| 750 |
struct aligned_storage {
|
| 751 |
typedef struct {
|
| 752 |
alignas(Alignment) unsigned char __data[Len];
|
| 753 |
} type;
|
| 754 |
};
|
| 755 |
```
|
| 756 |
|
| 757 |
+
— *end note*]
|
| 758 |
+
|
| 759 |
It is *implementation-defined* whether any extended alignment is
|
| 760 |
supported ([[basic.align]]).
|
| 761 |
|
| 762 |
+
Note A: For the `common_type` trait applied to a parameter pack `T` of
|
| 763 |
+
types, the member `type` shall be either defined or not present as
|
| 764 |
+
follows:
|
| 765 |
|
| 766 |
+
- If `sizeof...(T)` is zero, there shall be no member `type`.
|
| 767 |
+
- If `sizeof...(T)` is one, let `T0` denote the sole type constituting
|
| 768 |
+
the pack `T`. The member *typedef-name* `type` shall denote the same
|
| 769 |
+
type, if any, as `common_type_t<T0, T0>`; otherwise there shall be no
|
| 770 |
+
member `type`.
|
| 771 |
+
- If `sizeof...(T)` is two, let the first and second types constituting
|
| 772 |
+
`T` be denoted by `T1` and `T2`, respectively, and let `D1` and `D2`
|
| 773 |
+
denote the same types as `decay_t<T1>` and `decay_t<T2>`,
|
| 774 |
+
respectively.
|
| 775 |
+
- If `is_same_v<T1, D1>` is `false` or `is_same_v<T2, D2>` is `false`,
|
| 776 |
+
let `C` denote the same type, if any, as `common_type_t<D1, D2>`.
|
| 777 |
+
- Otherwise, let `C` denote the same type, if any, as
|
| 778 |
``` cpp
|
| 779 |
+
decay_t<decltype(false ? declval<D1>() : declval<D2>())>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 780 |
```
|
| 781 |
|
| 782 |
+
\[*Note 3*: This will not apply if there is a specialization
|
| 783 |
+
`common_type<D1, D2>`. — *end note*]
|
| 784 |
+
|
| 785 |
+
In either case, the member *typedef-name* `type` shall denote the same
|
| 786 |
+
type, if any, as `C`. Otherwise, there shall be no member `type`.
|
| 787 |
+
- If `sizeof...(T)` is greater than two, let `T1`, `T2`, and `R`,
|
| 788 |
+
respectively, denote the first, second, and (pack of) remaining types
|
| 789 |
+
constituting `T`. Let `C` denote the same type, if any, as
|
| 790 |
+
`common_type_t<T1, T2>`. If there is such a type `C`, the member
|
| 791 |
+
*typedef-name* `type` shall denote the same type, if any, as
|
| 792 |
+
`common_type_t<C, R...>`. Otherwise, there shall be no member `type`.
|
| 793 |
+
|
| 794 |
+
Note B: Notwithstanding the provisions of [[meta.type.synop]], and
|
| 795 |
+
pursuant to [[namespace.std]], a program may specialize
|
| 796 |
+
`common_type<T1, T2>` for types `T1` and `T2` such that
|
| 797 |
+
`is_same_v<T1, decay_t<T1>>` and `is_same_v<T2, decay_t<T2>>` are each
|
| 798 |
+
`true`.
|
| 799 |
+
|
| 800 |
+
[*Note 4*: Such specializations are needed when only explicit
|
| 801 |
+
conversions are desired between the template arguments. — *end note*]
|
| 802 |
+
|
| 803 |
+
Such a specialization need not have a member named `type`, but if it
|
| 804 |
+
does, that member shall be a *typedef-name* for an accessible and
|
| 805 |
+
unambiguous cv-unqualified non-reference type `C` to which each of the
|
| 806 |
+
types `T1` and `T2` is explicitly convertible. Moreover,
|
| 807 |
+
`common_type_t<T1, T2>` shall denote the same type, if any, as does
|
| 808 |
+
`common_type_t<T2, T1>`. No diagnostic is required for a violation of
|
| 809 |
+
this Note’s rules.
|
| 810 |
+
|
| 811 |
+
[*Example 1*:
|
| 812 |
+
|
| 813 |
Given these definitions:
|
| 814 |
|
| 815 |
``` cpp
|
| 816 |
+
using PF1 = bool (&)();
|
| 817 |
+
using PF2 = short (*)(long);
|
| 818 |
|
| 819 |
struct S {
|
| 820 |
operator PF2() const;
|
| 821 |
double operator()(char, int&);
|
| 822 |
void fn(long) const;
|
| 823 |
char data;
|
| 824 |
};
|
| 825 |
|
| 826 |
+
using PMF = void (S::*)(long) const;
|
| 827 |
+
using PMD = char S::*;
|
| 828 |
```
|
| 829 |
|
| 830 |
the following assertions will hold:
|
| 831 |
|
| 832 |
``` cpp
|
| 833 |
+
static_assert(is_same_v<invoke_result_t<S, int>, short>);
|
| 834 |
+
static_assert(is_same_v<invoke_result_t<S&, unsigned char, int&>, double>);
|
| 835 |
+
static_assert(is_same_v<invoke_result_t<PF1>, bool>);
|
| 836 |
+
static_assert(is_same_v<invoke_result_t<PMF, unique_ptr<S>, int>, void>);
|
| 837 |
+
static_assert(is_same_v<invoke_result_t<PMD, S>, char&&>);
|
| 838 |
+
static_assert(is_same_v<invoke_result_t<PMD, const S*>, const char&>);
|
| 839 |
```
|
| 840 |
|
| 841 |
+
— *end example*]
|
| 842 |
+
|
| 843 |
+
### Logical operator traits <a id="meta.logical">[[meta.logical]]</a>
|
| 844 |
+
|
| 845 |
+
This subclause describes type traits for applying logical operators to
|
| 846 |
+
other type traits.
|
| 847 |
+
|
| 848 |
+
``` cpp
|
| 849 |
+
template<class... B> struct conjunction : see below { };
|
| 850 |
+
```
|
| 851 |
+
|
| 852 |
+
The class template `conjunction` forms the logical conjunction of its
|
| 853 |
+
template type arguments.
|
| 854 |
+
|
| 855 |
+
For a specialization `conjunction<B1, ..., BN>`, if there is a template
|
| 856 |
+
type argument `Bi` for which `bool(Bi::value)` is `false`, then
|
| 857 |
+
instantiating `conjunction<B1, ..., BN>::value` does not require the
|
| 858 |
+
instantiation of `Bj::value` for `j > i`.
|
| 859 |
+
|
| 860 |
+
[*Note 1*: This is analogous to the short-circuiting behavior of the
|
| 861 |
+
built-in operator `&&`. — *end note*]
|
| 862 |
+
|
| 863 |
+
Every template type argument for which `Bi::value` is instantiated shall
|
| 864 |
+
be usable as a base class and shall have a member `value` which is
|
| 865 |
+
convertible to `bool`, is not hidden, and is unambiguously available in
|
| 866 |
+
the type.
|
| 867 |
+
|
| 868 |
+
The specialization `conjunction<B1, ..., BN>` has a public and
|
| 869 |
+
unambiguous base that is either
|
| 870 |
+
|
| 871 |
+
- the first type `Bi` in the list `true_type, B1, ..., BN` for which
|
| 872 |
+
`bool(Bi::value)` is `false`, or
|
| 873 |
+
- if there is no such `Bi`, the last type in the list.
|
| 874 |
+
|
| 875 |
+
[*Note 2*: This means a specialization of `conjunction` does not
|
| 876 |
+
necessarily inherit from either `true_type` or
|
| 877 |
+
`false_type`. — *end note*]
|
| 878 |
+
|
| 879 |
+
The member names of the base class, other than `conjunction` and
|
| 880 |
+
`operator=`, shall not be hidden and shall be unambiguously available in
|
| 881 |
+
`conjunction`.
|
| 882 |
+
|
| 883 |
+
``` cpp
|
| 884 |
+
template<class... B> struct disjunction : see below { };
|
| 885 |
+
```
|
| 886 |
+
|
| 887 |
+
The class template `disjunction` forms the logical disjunction of its
|
| 888 |
+
template type arguments.
|
| 889 |
+
|
| 890 |
+
For a specialization `disjunction<B1, ..., BN>`, if there is a template
|
| 891 |
+
type argument `Bi` for which `bool(Bi::value)` is `true`, then
|
| 892 |
+
instantiating `disjunction<B1, ..., BN>::value` does not require the
|
| 893 |
+
instantiation of `Bj::value` for `j > i`.
|
| 894 |
+
|
| 895 |
+
[*Note 3*: This is analogous to the short-circuiting behavior of the
|
| 896 |
+
built-in operator `||`. — *end note*]
|
| 897 |
+
|
| 898 |
+
Every template type argument for which `Bi::value` is instantiated shall
|
| 899 |
+
be usable as a base class and shall have a member `value` which is
|
| 900 |
+
convertible to `bool`, is not hidden, and is unambiguously available in
|
| 901 |
+
the type.
|
| 902 |
+
|
| 903 |
+
The specialization `disjunction<B1, ..., BN>` has a public and
|
| 904 |
+
unambiguous base that is either
|
| 905 |
+
|
| 906 |
+
- the first type `Bi` in the list `false_type, B1, ..., BN` for which
|
| 907 |
+
`bool(Bi::value)` is `true`, or
|
| 908 |
+
- if there is no such `Bi`, the last type in the list.
|
| 909 |
+
|
| 910 |
+
[*Note 4*: This means a specialization of `disjunction` does not
|
| 911 |
+
necessarily inherit from either `true_type` or
|
| 912 |
+
`false_type`. — *end note*]
|
| 913 |
+
|
| 914 |
+
The member names of the base class, other than `disjunction` and
|
| 915 |
+
`operator=`, shall not be hidden and shall be unambiguously available in
|
| 916 |
+
`disjunction`.
|
| 917 |
+
|
| 918 |
+
``` cpp
|
| 919 |
+
template<class B> struct negation : see below { };
|
| 920 |
+
```
|
| 921 |
+
|
| 922 |
+
The class template `negation` forms the logical negation of its template
|
| 923 |
+
type argument. The type `negation<B>` is a `UnaryTypeTrait` with a base
|
| 924 |
+
characteristic of `bool_constant<!bool(B::value)>`.
|
| 925 |
+
|