From 0915d58068abf0e3d33b21e570ba07014fd3ede3 Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Tue, 6 Jan 2026 16:37:44 +0800 Subject: [PATCH 1/7] feat(): page: util hash --- src/content/docs/cpp/library/utility/hash.mdx | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/content/docs/cpp/library/utility/hash.mdx diff --git a/src/content/docs/cpp/library/utility/hash.mdx b/src/content/docs/cpp/library/utility/hash.mdx new file mode 100644 index 00000000..f7168621 --- /dev/null +++ b/src/content/docs/cpp/library/utility/hash.mdx @@ -0,0 +1,250 @@ +--- +title: std::hash +cppdoc: + revision: + since: C++11 +--- + +import { CppHeader } from "@components/header"; +import { Decl, DeclDoc } from "@components/decl-doc"; +import { Desc, DescList } from "@components/desc-list"; +import Missing from "@components/Missing.astro"; +import { ParamDoc, ParamDocList } from "@components/param-doc"; +import { Revision, RevisionBlock } from "@components/revision"; + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + +Defined in header . + + + + + ```cpp + template< class Key > + struct hash; + ``` + + + + The unordered associative containers `std::unordered_set`, `std::unordered_multiset`, `std::unordered_map`, `std::unordered_multimap` use specializations of the template std::hash as the default hash function. + + +Given a type `Key`, each specialization `std::hash` is either _enabled_ or _disabled_ : + +- If `std::hash` is not provided by the program or the user, it is disabled. +- Otherwise, `std::hash` is enabled if all following conditions are satisfied: + - All following requirements are satisfied: + - [Hash](../named_req/Hash.html "cpp/named req/Hash") (with `Key` as the function call argument type) + - [DefaultConstructible](../named_req/DefaultConstructible.html "cpp/named req/DefaultConstructible") + - [CopyAssignable](../named_req/CopyAssignable.html "cpp/named req/CopyAssignable") + - [Swappable](../named_req/Swappable.html "cpp/named req/Swappable") + + - Given the following values: + - h, an object of type `std::hash`. + - k1 and k2, objects of type `Key`. + All following requirements are satisfied: + - If k1 \== k2 is true, h(k1) \== h(k2) is also true. + - Unless `std::hash` is a [program-defined specialization](../language/type-id.html#Program-defined_type "cpp/language/type"), h(k1) will never throw an exception. + +- Otherwise, `std::hash` is disabled. + +Disabled specializations do not satisfy [Hash](../named_req/Hash.html "cpp/named req/Hash"), do not satisfy [FunctionObject](../named_req/FunctionObject.html "cpp/named req/FunctionObject"), and following values are all false: + +- `std::is_default_constructible>::value` +- `std::is_copy_constructible>::value` +- `std::is_move_constructible>::value` +- `std::is_copy_assignable>::value` +- `std::is_move_assignable>::value` + +In other words, they exist, but cannot be used. + + + + Nested types: + |Name|Definition| + |---|---| + |`argument_type` (deprecared in C++ 17)| Key| + |`result_type` (deprecared in C++ 17)| size_t| + + + + +### Member functions +| | | +|---|---| +|`constuctor` | constructs a hash function object
(public member function)| +|`operator()` | calculates the hash of the argument
(public member function)| + + +### Standard library specializations +Each header that declares the template std::hash also provides enabled specializations of std::hash for the following types: + +- all cv-unqualified arithmetic types +- all cv-unqualified enumeration types +- all cv-unqualified pointer types +- std::nullptr_t + +On top of that, some headers also provide other enabled std::hash specializations for library types (see below). + + + + + + + For all std::hash specializations provided by the standard library except the following, all their member functions are noexcept: + - `std::hash` + - `std::hash` + - `std::hash` + + + - `std::hash` + - `std::hash` + - `std::hash` + + + + + + +## Notes + +The actual hash functions are implementation-dependent and are not required to fulfill any other quality criteria except those specified above. Notably, some implementations use trivial (identity) hash functions which map an integer to itself. In other words, these hash functions are designed to work with unordered associative containers, but not as cryptographic hashes, for example. + +Hash functions are only required to produce the same result for the same input within a single execution of a program; this allows salted hashes that prevent collision denial-of-service attacks. + +There is no specialization for C strings. `std::hash` produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array. + +Additional specializations for `std::pair` and the standard container types, as well as utility functions to compose hashes are available in `boost::hash`. + + +## Example + +```cpp +#include +#include +#include +#include +#include +#include + +struct S +{ + std::string first_name; + std::string last_name; + bool operator==(const S&) const = default; // since C++20 +}; + +// Before C++20. +// bool operator==(const S& lhs, const S& rhs) +// { +// return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name; +// } + +// Custom hash can be a standalone function object. +struct MyHash +{ + std::size_t operator()(const S& s) const noexcept + { + std::size_t h1 = std::hash{}(s.first_name); + std::size_t h2 = std::hash{}(s.last_name); + return h1 ^ (h2 << 1); // or use boost::hash_combine + } +}; + +// Custom specialization of std::hash can be injected in namespace std. +template<> +struct std::hash +{ + std::size_t operator()(const S& s) const noexcept + { + std::size_t h1 = std::hash{}(s.first_name); + std::size_t h2 = std::hash{}(s.last_name); + return h1 ^ (h2 << 1); // or use boost::hash_combine + } +}; + +int main() +{ + std::string str = "Meet the new boss..."; + std::size_t str_hash = std::hash{}(str); + std::cout << "hash(" << std::quoted(str) << ") =\t" << str_hash << '\n'; + + S obj = {"Hubert", "Farnsworth"}; + // Using the standalone function object. + std::cout << "hash(" << std::quoted(obj.first_name) << ", " + << std::quoted(obj.last_name) << ") =\t" + << MyHash{}(obj) << " (using MyHash) or\n\t\t\t\t" + << std::hash{}(obj) << " (using injected specialization)\n"; + + // Custom hash makes it possible to use custom types in unordered containers. + // The example will use the injected std::hash specialization above, + // to use MyHash instead, pass it as a second template argument. + std::unordered_set names = {obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"}}; + for (auto const& s: names) + std::cout << std::quoted(s.first_name) << ' ' + << std::quoted(s.last_name) << '\n'; +} +``` + +Possible outputs: + +```cpp +hash("Meet the new boss...") = 10656026664466977650 +hash("Hubert", "Farnsworth") = 12922914235676820612 (using MyHash) or + 12922914235676820612 (using injected specialization) +"Bender" "Rodriguez" +"Turanga" "Leela" +"Hubert" "Farnsworth" +``` + +```cpp +// Simple move constructor +// the expression "arg.member" is lvalue +A(A&& arg) : member(std::move(arg.member)) {} + +// Simple move assignment operator +A& operator=(A&& other) { + member = std::move(other.member); + return *this; +} +``` + +## Defect reports + +The following behavior-changing defect reports were applied retroactively to previously published C++ standards. + +| DR | Applied to | Behavior as published | Correct behavior | +| --- | --- | --- | --- | +| [LWG 2119](https://cplusplus.github.io/LWG/issue2119) | C++11 | specializations for extended integer types were missing | provided | +| [LWG 2148](https://cplusplus.github.io/LWG/issue2148) | C++11 | specializations for enumerations were missing | provided | +| [LWG 2543](https://cplusplus.github.io/LWG/issue2543) | C++11 | `std::hash` might not be SFINAE-friendly | made SFINAE-friendly | +| [LWG 2817](https://cplusplus.github.io/LWG/issue2817) | C++11 | specialization for [std::nullptr\_t](../types/nullptr_t.html "cpp/types/nullptr_t") was missing | provided | + From 6f4d6247fde793e7978c915ff0a22d2fd406e1b2 Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Tue, 6 Jan 2026 17:11:21 +0800 Subject: [PATCH 2/7] feat(std::hash): page for `operator()` --- src/content/docs/cpp/library/utility/hash.mdx | 24 ++---- .../library/utility/hash/operator-call.mdx | 83 +++++++++++++++++++ 2 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 src/content/docs/cpp/library/utility/hash/operator-call.mdx diff --git a/src/content/docs/cpp/library/utility/hash.mdx b/src/content/docs/cpp/library/utility/hash.mdx index f7168621..bfb78609 100644 --- a/src/content/docs/cpp/library/utility/hash.mdx +++ b/src/content/docs/cpp/library/utility/hash.mdx @@ -48,7 +48,7 @@ Defined in header . ```cpp - template< class Key > + template struct hash; ``` @@ -68,10 +68,10 @@ Given a type `Key`, each specialization `std::hash` is either _enabled_ or - [Swappable](../named_req/Swappable.html "cpp/named req/Swappable") - Given the following values: - - h, an object of type `std::hash`. - - k1 and k2, objects of type `Key`. + - `h`, an object of type `std::hash`. + - `k1` and `k2`, objects of type `Key`. All following requirements are satisfied: - - If k1 \== k2 is true, h(k1) \== h(k2) is also true. + - If `k1 == k2` is true, `h(k1) == h(k2)` is also true. - Unless `std::hash` is a [program-defined specialization](../language/type-id.html#Program-defined_type "cpp/language/type"), h(k1) will never throw an exception. - Otherwise, `std::hash` is disabled. @@ -100,8 +100,8 @@ In other words, they exist, but cannot be used. ### Member functions | | | |---|---| -|`constuctor` | constructs a hash function object
(public member function)| -|`operator()` | calculates the hash of the argument
(public member function)| +|(constuctor) | constructs a hash function object | +|[`operator()`](./operator-call/) | calculates the hash of the argument | ### Standard library specializations @@ -225,18 +225,6 @@ hash("Hubert", "Farnsworth") = 12922914235676820612 (using MyHash) or "Hubert" "Farnsworth" ``` -```cpp -// Simple move constructor -// the expression "arg.member" is lvalue -A(A&& arg) : member(std::move(arg.member)) {} - -// Simple move assignment operator -A& operator=(A&& other) { - member = std::move(other.member); - return *this; -} -``` - ## Defect reports The following behavior-changing defect reports were applied retroactively to previously published C++ standards. diff --git a/src/content/docs/cpp/library/utility/hash/operator-call.mdx b/src/content/docs/cpp/library/utility/hash/operator-call.mdx new file mode 100644 index 00000000..b005a4c8 --- /dev/null +++ b/src/content/docs/cpp/library/utility/hash/operator-call.mdx @@ -0,0 +1,83 @@ +--- +title: std::hash::operator() +cppdoc: + revision: + since: C++11 +--- + +import { ParamDoc, ParamDocList } from "@components/param-doc"; + +Specializations of `std::hash` should define an `operator()` that: + +- Takes a single argument key of type `Key`. +- Returns a value of type `std::size_t` that represents the hash value of key. +- For two parameters `k1` and `k2` that are equal, `std::hash()(k1) == std::hash()(k2)`. +- For two different parameters `k1` and `k2` that are not equal, the probability that `std::hash()(k1) == std::hash()(k2)` should be very small, approaching `1.0 / std::numeric_limits::max()`. + + +## Parameters + + + the object to be hashed + + + +## Return value +A `std::size_t` representing the hash value. + +## Exceptions +Hash functions should not throw exceptions. + +## Example +The following code shows how to specialize the std::hash template for a custom class. The hash function uses Fowler–Noll–Vo hash algorithm. + +```cpp +#include +#include +#include +#include + +struct Employee +{ + std::string name; + std::uint64_t ID; +}; + +namespace std +{ + template <> + class hash + { + public: + std::uint64_t operator()(const Employee& employee) const + { + // computes the hash of an employee using a variant + // of the Fowler-Noll-Vo hash function + constexpr std::uint64_t prime{0x100000001B3}; + std::uint64_t result{0xcbf29ce484222325}; + + for (std::uint64_t i{}, ie = employee.name.size(); i != ie; ++i) + result = (result * prime) ^ employee.name[i]; + + return result ^ (employee.ID << 1); + } + }; +} + +int main() +{ + Employee employee; + employee.name = "Zaphod Beeblebrox"; + employee.ID = 42; + + std::hash hash_fn; + std::cout << hash_fn(employee) << '\n'; +} +``` + +Output: + +```cpp +12615575401975788567 +``` + From 74fd43c58bbb2d9ba0a061ea91a7c1610b8d5b3d Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Tue, 6 Jan 2026 17:22:18 +0800 Subject: [PATCH 3/7] fix(std::hash): use doclink --- src/content/docs/cpp/library/utility/hash.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/content/docs/cpp/library/utility/hash.mdx b/src/content/docs/cpp/library/utility/hash.mdx index bfb78609..5c4ef269 100644 --- a/src/content/docs/cpp/library/utility/hash.mdx +++ b/src/content/docs/cpp/library/utility/hash.mdx @@ -11,6 +11,7 @@ import { Desc, DescList } from "@components/desc-list"; import Missing from "@components/Missing.astro"; import { ParamDoc, ParamDocList } from "@components/param-doc"; import { Revision, RevisionBlock } from "@components/revision"; +import DocLink from "@components/DocLink.astro" Defined in header . @@ -101,7 +102,7 @@ In other words, they exist, but cannot be used. | | | |---|---| |(constuctor) | constructs a hash function object | -|[`operator()`](./operator-call/) | calculates the hash of the argument | +| `operator()` | calculates the hash of the argument | ### Standard library specializations From 35e9b8910770882faefcf0ad85c7184ade232d8a Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Wed, 21 Jan 2026 01:02:59 +0800 Subject: [PATCH 4/7] feat(named_req) Hashable, DefaultConstructible, Destructible --- .../named_req/DefaultConstructible.mdx | 91 +++++++++++++++++++ .../cpp/language/named_req/Destructible.mdx | 60 ++++++++++++ .../docs/cpp/language/named_req/Hash.mdx | 58 ++++++++++++ .../docs/cpp/language/named_req/_meta.yml | 1 + 4 files changed, 210 insertions(+) create mode 100644 src/content/docs/cpp/language/named_req/DefaultConstructible.mdx create mode 100644 src/content/docs/cpp/language/named_req/Destructible.mdx create mode 100644 src/content/docs/cpp/language/named_req/Hash.mdx create mode 100644 src/content/docs/cpp/language/named_req/_meta.yml diff --git a/src/content/docs/cpp/language/named_req/DefaultConstructible.mdx b/src/content/docs/cpp/language/named_req/DefaultConstructible.mdx new file mode 100644 index 00000000..3c650e59 --- /dev/null +++ b/src/content/docs/cpp/language/named_req/DefaultConstructible.mdx @@ -0,0 +1,91 @@ +--- +title: "C++ named requirements: DefaultConstructible" +cppdoc: + revision: + since: C++11 +--- + +import { DR, DRList } from "@components/defect-report"; +import { Desc, DescList } from "@components/desc-list"; + +Specifies that an instance of the type can be default constructed. + + +## Requirements +The type `T` satisfies _DefaultConstructible_ if all following statements and expressions are valid and have their specified effects: + +Given + +- `u`, an expression of type `T`. + +- `u`, an lvalue expression of type `Key`. + +|Expression/Statement| Postcondition| +|---|---| +|`T u;`| The object `u` is default-initialized.| +|`T u{};`| The object `u` is value-initialized or aggregate-initialized.| +|`T()`| All resources owned by `u` are reclaimed, no exceptions are thrown.| +|`T{}`| A temporary object of type `T` is value-initialized or aggregate-initialized.| + +## Notes + +For objects of non-aggregate class type, a public default constructor must be defined (either user-defined or implicitly defined) to satisfy _DefaultConstructible_. + +Non-const objects of non-class object type are always _DefaultConstructible_. + +Const non-class types are not _DefaultConstructible_. + +Const aggregate types are not _DefaultConstructible_ if any of their members is an object of non-class type. + +Non-object types (function types, reference types, and the (possibly cv-qualified) type void) as well as the const non-object types are never _DefaultConstructible_. + +# Defect reports + +The following behavior-changing defect reports were applied retroactively to previously published C++ standards. + + + + + the requirements of _DefaultConstructible_ were missing + + + added + + + + + initialzing an object of a _DefaultConstructible_ type with an +empty initializer could only result in value-initialization + + + can also lead to aggregate-initialization + + + +## See also + + + + + + `std::is_default_constructible` + + + `std::is_trivially_default_constructible` + + + `std::is_nothrow_default_constructible` + + + checks if a type has a default constructor + + + + + `default_initializable` + + + specifies that an object of a type can be default constructed + + + diff --git a/src/content/docs/cpp/language/named_req/Destructible.mdx b/src/content/docs/cpp/language/named_req/Destructible.mdx new file mode 100644 index 00000000..71db9125 --- /dev/null +++ b/src/content/docs/cpp/language/named_req/Destructible.mdx @@ -0,0 +1,60 @@ +--- +title: "C++ named requirements: Destructible" +cppdoc: + revision: + since: C++11 +--- + +import { DR, DRList } from "@components/defect-report"; +import { Desc, DescList } from "@components/desc-list"; + +Specifies that an instance of the type can be destructed. + + +## Requirements +The type `T` satisfies `Destructible` if + +Given + +- `u`, an expression of type `T`. + +- `u`, an lvalue expression of type `Key`. + +|Expression| Post-Conditions| +|---|---| +|`u.~T()`| All resources owned by `u` are reclaimed, no exceptions are thrown.| + +## Notes + + +Destructors are called implicitly at the end of object lifetime such as when leaving scope or by the delete-expression. Explicit destructor call as shown in the type requirement table is rare. + +Thanks to pseudo destructor call, all scalar types meet the requirement of Destructible, while array types and reference types do not. Note that `std::is_destructible` allows arrays and reference types. + +## See also + + + + + + `std::is_destructible` + + + `std::is_trivially_destructible` + + + `std::is_nothrow_destructible` + + + checks if a type has a non-deleted destructor + + + + + `destructible` + + + specifies that an object of the type can be destroyed + + + diff --git a/src/content/docs/cpp/language/named_req/Hash.mdx b/src/content/docs/cpp/language/named_req/Hash.mdx new file mode 100644 index 00000000..dfb8c6cc --- /dev/null +++ b/src/content/docs/cpp/language/named_req/Hash.mdx @@ -0,0 +1,58 @@ +--- +title: "C++ named requirements: Hash" +cppdoc: + revision: + since: C++11 +--- + +import { DR, DRList } from "@components/defect-report"; +import { Desc, DescList } from "@components/desc-list"; + +A ***Hash*** is a function object for which the output depends only on the input and has a very low probability of yielding the same output given different input values. + + +## Requirements +The type `T` satisfies `Hash` if + +The type `T` satisfies `FunctionObject`, `CopyConstructible`, `Destructible`, and +Given + +- `h`, a value of type `T` or const `T`, whose argument type is `Key`, +- `k`, a value of type convertible to `Key` or `const Key`, +- `u`, an lvalue expression of type `Key`. + +The following expressions must be valid and have their specified effects. + +|Expression| Return type| Requirements| +|---|---|---| +|`h(k)`| `std::size_t`|The returned value depends only on the value of `k` for the duration of the program.
All evaluations of `h(k)` executed within a given execution of a program yield the same result for the same value of `k`.
The probability of `h(a) == h(b)` for `a != b` should approach `1.0 / std::numeric_limits::max()`.| +|`h(u)` | `std::size_t` | `u` is not modified.| + +## Standard Library + + + + + + `hash` + + + hash function object + + + +# Defect reports + +The following behavior-changing defect reports were applied retroactively to previously published C++ standards. + + + + + same results for same arguments were required in all cases + + + only required within a single execution + + + + diff --git a/src/content/docs/cpp/language/named_req/_meta.yml b/src/content/docs/cpp/language/named_req/_meta.yml new file mode 100644 index 00000000..7668e33f --- /dev/null +++ b/src/content/docs/cpp/language/named_req/_meta.yml @@ -0,0 +1 @@ +label: Name Requirements From 3d7d464528f7ce06d90110c1314d399de8e484c0 Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Wed, 21 Jan 2026 01:03:24 +0800 Subject: [PATCH 5/7] feat(hash): update link --- src/content/docs/cpp/library/utility/hash.mdx | 85 +++++++++---------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/src/content/docs/cpp/library/utility/hash.mdx b/src/content/docs/cpp/library/utility/hash.mdx index 5c4ef269..fa7f102a 100644 --- a/src/content/docs/cpp/library/utility/hash.mdx +++ b/src/content/docs/cpp/library/utility/hash.mdx @@ -12,38 +12,31 @@ import Missing from "@components/Missing.astro"; import { ParamDoc, ParamDocList } from "@components/param-doc"; import { Revision, RevisionBlock } from "@components/revision"; import DocLink from "@components/DocLink.astro" +import { Card } from "@astrojs/starlight/components"; +import FlexTable from "@components/FlexTable.astro"; + + + + + + + + + + + + + + + + + + + + + -Defined in header . -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . - -Defined in header . @@ -60,24 +53,24 @@ Defined in header . Given a type `Key`, each specialization `std::hash` is either _enabled_ or _disabled_ : -- If `std::hash` is not provided by the program or the user, it is disabled. -- Otherwise, `std::hash` is enabled if all following conditions are satisfied: - - All following requirements are satisfied: - - [Hash](../named_req/Hash.html "cpp/named req/Hash") (with `Key` as the function call argument type) - - [DefaultConstructible](../named_req/DefaultConstructible.html "cpp/named req/DefaultConstructible") - - [CopyAssignable](../named_req/CopyAssignable.html "cpp/named req/CopyAssignable") - - [Swappable](../named_req/Swappable.html "cpp/named req/Swappable") - - - Given the following values: - - `h`, an object of type `std::hash`. - - `k1` and `k2`, objects of type `Key`. +- If `std::hash` is not provided by the program or the user, it is disabled. +- Otherwise, `std::hash` is enabled if all following conditions are satisfied: + - All following requirements are satisfied: + - `Hash` (with `Key` as the function call argument type) + - `DefaultConstructible` + - [CopyAssignable](../named_req/CopyAssignable.html "cpp/named req/CopyAssignable") + - [Swappable](../named_req/Swappable.html "cpp/named req/Swappable") + + - Given the following values: + - `h`, an object of type `std::hash`. + - `k1` and `k2`, objects of type `Key`. All following requirements are satisfied: - - If `k1 == k2` is true, `h(k1) == h(k2)` is also true. - - Unless `std::hash` is a [program-defined specialization](../language/type-id.html#Program-defined_type "cpp/language/type"), h(k1) will never throw an exception. + - If `k1 == k2` is true, `h(k1) == h(k2)` is also true. + - Unless `std::hash` is a [program-defined specialization](../language/type-id.html#Program-defined_type "cpp/language/type"), h(k1) will never throw an exception. - Otherwise, `std::hash` is disabled. -Disabled specializations do not satisfy [Hash](../named_req/Hash.html "cpp/named req/Hash"), do not satisfy [FunctionObject](../named_req/FunctionObject.html "cpp/named req/FunctionObject"), and following values are all false: +Disabled specializations do not satisfy `Hash` , do not satisfy [FunctionObject](../named_req/FunctionObject.html "cpp/named req/FunctionObject"), and following values are all false: - `std::is_default_constructible>::value` - `std::is_copy_constructible>::value` @@ -92,8 +85,8 @@ In other words, they exist, but cannot be used. Nested types: |Name|Definition| |---|---| - |`argument_type` (deprecared in C++ 17)| Key| - |`result_type` (deprecared in C++ 17)| size_t| + |`argument_type` (deprecared in C++ 17)| `Key`| + |`result_type` (deprecared in C++ 17)| `size_t`| From f89163ec5ab2fb249f93b91b89ee16f37aeeffd6 Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Wed, 21 Jan 2026 02:17:27 +0800 Subject: [PATCH 6/7] feat(named_req): Swappable, CopyAssignable --- .../language/named_req/copy-asssignable.mdx | 59 ++++++ ...ructible.mdx => default-constructible.mdx} | 14 +- .../{Destructible.mdx => destructible.mdx} | 10 +- .../language/named_req/{Hash.mdx => hash.mdx} | 4 +- .../docs/cpp/language/named_req/swappable.mdx | 184 ++++++++++++++++++ 5 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 src/content/docs/cpp/language/named_req/copy-asssignable.mdx rename src/content/docs/cpp/language/named_req/{DefaultConstructible.mdx => default-constructible.mdx} (88%) rename src/content/docs/cpp/language/named_req/{Destructible.mdx => destructible.mdx} (84%) rename src/content/docs/cpp/language/named_req/{Hash.mdx => hash.mdx} (92%) create mode 100644 src/content/docs/cpp/language/named_req/swappable.mdx diff --git a/src/content/docs/cpp/language/named_req/copy-asssignable.mdx b/src/content/docs/cpp/language/named_req/copy-asssignable.mdx new file mode 100644 index 00000000..c1a1eda7 --- /dev/null +++ b/src/content/docs/cpp/language/named_req/copy-asssignable.mdx @@ -0,0 +1,59 @@ +--- +title: "C++ named requirements: CopyAssignable" +cppdoc: + revision: + since: C++11 +--- + +import { DR, DRList } from "@components/defect-report"; +import { Desc, DescList } from "@components/desc-list"; +import Missing from "@components/Missing.astro"; +import { Revision, RevisionBlock } from "@components/revision"; + +Specifies that an instance of the type can be copy-assigned from an lvalue expression. + + +## Requirements + +The type T satisfies _CopyAssignable_ if + +- The type T satisfies _MoveAssignable_, and + +Given + +- `t`, a modifiable lvalue expression of type `T`, +- `v`, an lvalue expression of type `T` or `const T` or an rvalue expression of type `const T`. + +The following expressions must be valid and have their specified effects. + +|Expression| Return type | Return value |Post-conditions| +|---|---|---|---| +|`t=v`| `T&` | `t` |The value of t is equivalent to the value of v.
The value of v is unchanged. | + +## See also + + + + + + `std::is_copy_assignable` + + + `std::is_trivially_copy_assignable` + + + `std::is_nothrow_copy_assignable` + + + checks if a type has a copy assignment operator + + + + + `assignable_from` + + + specifies that an object of a type can be default constructed + + + diff --git a/src/content/docs/cpp/language/named_req/DefaultConstructible.mdx b/src/content/docs/cpp/language/named_req/default-constructible.mdx similarity index 88% rename from src/content/docs/cpp/language/named_req/DefaultConstructible.mdx rename to src/content/docs/cpp/language/named_req/default-constructible.mdx index 3c650e59..539b09f0 100644 --- a/src/content/docs/cpp/language/named_req/DefaultConstructible.mdx +++ b/src/content/docs/cpp/language/named_req/default-constructible.mdx @@ -7,6 +7,8 @@ cppdoc: import { DR, DRList } from "@components/defect-report"; import { Desc, DescList } from "@components/desc-list"; +import Missing from "@components/Missing.astro"; +import { Revision, RevisionBlock } from "@components/revision"; Specifies that an instance of the type can be default constructed. @@ -44,7 +46,7 @@ Non-object types (function types, reference types, and the (possibly cv-qualifie The following behavior-changing defect reports were applied retroactively to previously published C++ standards. - + the requirements of _DefaultConstructible_ were missing @@ -52,7 +54,7 @@ The following behavior-changing defect reports were applied retroactively to pre added - + initialzing an object of a _DefaultConstructible_ type with an empty initializer could only result in value-initialization @@ -67,13 +69,13 @@ empty initializer could only result in value-initialization - + `std::is_default_constructible` - + `std::is_trivially_default_constructible` - + `std::is_nothrow_default_constructible` @@ -81,7 +83,7 @@ empty initializer could only result in value-initialization - + `default_initializable` diff --git a/src/content/docs/cpp/language/named_req/Destructible.mdx b/src/content/docs/cpp/language/named_req/destructible.mdx similarity index 84% rename from src/content/docs/cpp/language/named_req/Destructible.mdx rename to src/content/docs/cpp/language/named_req/destructible.mdx index 71db9125..5c43a521 100644 --- a/src/content/docs/cpp/language/named_req/Destructible.mdx +++ b/src/content/docs/cpp/language/named_req/destructible.mdx @@ -7,6 +7,8 @@ cppdoc: import { DR, DRList } from "@components/defect-report"; import { Desc, DescList } from "@components/desc-list"; +import Missing from "@components/Missing.astro"; +import { Revision, RevisionBlock } from "@components/revision"; Specifies that an instance of the type can be destructed. @@ -36,13 +38,13 @@ Thanks to pseudo destructor call, all scalar types meet the requirement of Destr - + `std::is_destructible` - + `std::is_trivially_destructible` - + `std::is_nothrow_destructible` @@ -50,7 +52,7 @@ Thanks to pseudo destructor call, all scalar types meet the requirement of Destr - + `destructible` diff --git a/src/content/docs/cpp/language/named_req/Hash.mdx b/src/content/docs/cpp/language/named_req/hash.mdx similarity index 92% rename from src/content/docs/cpp/language/named_req/Hash.mdx rename to src/content/docs/cpp/language/named_req/hash.mdx index dfb8c6cc..2b1ae153 100644 --- a/src/content/docs/cpp/language/named_req/Hash.mdx +++ b/src/content/docs/cpp/language/named_req/hash.mdx @@ -7,6 +7,8 @@ cppdoc: import { DR, DRList } from "@components/defect-report"; import { Desc, DescList } from "@components/desc-list"; +import DocLink from "@components/DocLink.astro" +import { Revision, RevisionBlock } from "@components/revision"; A ***Hash*** is a function object for which the output depends only on the input and has a very low probability of yielding the same output given different input values. @@ -46,7 +48,7 @@ The following expressions must be valid and have their specified effects. The following behavior-changing defect reports were applied retroactively to previously published C++ standards. - + same results for same arguments were required in all cases diff --git a/src/content/docs/cpp/language/named_req/swappable.mdx b/src/content/docs/cpp/language/named_req/swappable.mdx new file mode 100644 index 00000000..128ac466 --- /dev/null +++ b/src/content/docs/cpp/language/named_req/swappable.mdx @@ -0,0 +1,184 @@ +--- +title: "C++ named requirements: Swappable" +cppdoc: + revision: + since: C++11 +--- + +import { CppHeader } from "@components/header"; +import { DR, DRList } from "@components/defect-report"; +import { Desc, DescList } from "@components/desc-list"; +import Missing from "@components/Missing.astro"; +import { Revision, RevisionBlock } from "@components/revision"; + +Any lvalue or rvalue of this type can be swapped with any lvalue or rvalue of some other type, using unqualified function call `swap()` in the context where both `std::swap` and the user-defined `swap()`s are visible. + + +## Requirements + +Type U is swappable with type T if, for any object u of type U and any object t of type T, + +Given + +- `u`, an expression of type `T`. + +- `u`, an lvalue expression of type `Key`. + + + + + + + + + + + + + + + + + + + + +
Expression Requirements Semantics
+```c++ +#include // until C++11 +#include // since C++11 +using std::swap; +swap(u, t); +``` + +After the call, the value of `t` is the value held by `u` before the call, and the value of `u` is the value held by `t` before the call. + +Calls the function named `swap()` found by overload resolution among all functions with that name that are found by argument-dependent lookup and the two `std::swap` templates defined in the header + + + +
+```c++ +#include // until C++11 +#include // since C++11 +using std::swap; +swap(u, t); +``` + +Same + +Same +
+ +Many standard library functions (for example, many algorithms) expect their arguments to satisfy Swappable, which means that any time the standard library performs a swap, it uses the equivalent of using std::swap; swap(t, u);. + +Typical implementations either + +1. Define a non-member swap in the enclosing namespace, which may forward to a member swap if access to non-public data members is required. +2. Define a friend function in-class (this approach hides the class-specific swap from name lookup other than ADL). + +## Notes + +Notes +It is unspecified whether + is actually included when the standard library functions perform the swap, so the user-provided swap() should not expect it to be included. + + +## Example + +```c++ +#include +#include + +struct IntVector +{ + std::vector v; + + IntVector& operator=(IntVector) = delete; // not assignable + + void swap(IntVector& other) + { + v.swap(other.v); + } + + void operator()(auto rem, auto term = " ") + { + std::cout << rem << "{{"; + for (int n{}; int e : v) + std::cout << (n++ ? ", " : "") << e; + std::cout << "}}" << term; + } +}; + +void swap(IntVector& v1, IntVector& v2) +{ + v1.swap(v2); +} + +int main() +{ + IntVector v1{{1, 1, 1, 1}}, v2{{2222, 2222}}; + + auto prn = [&]{ v1("v1", ", "), v2("v2", ";\n"); }; + +// std::swap(v1, v2); // Compiler error! std::swap requires MoveAssignable + prn(); + std::iter_swap(&v1, &v2); // OK: library calls unqualified swap() + prn(); + std::ranges::swap(v1, v2); // OK: library calls unqualified swap() + prn(); +} +``` + +Output: + +``` +v1{{1, 1, 1, 1}}, v2{{2222, 2222}}; +v1{{2222, 2222}}, v2{{1, 1, 1, 1}}; +v1{{1, 1, 1, 1}}, v2{{2222, 2222}}; +``` + +## Defect reports + +The following behavior-changing defect reports were applied retroactively to previously published C++ standards. + + + + it was unclear how the standard library uses swap + + + clarified to use both `std::` and ADL-found swap + + + +## See also + + + + + + `std::is_swappable_with` + + + `std::is_swappable` + + + `std::is_nothrow_swappable_with` + + + `std::is_nothrow_swappable` + + + checks if objects of a type can be swapped with objects of same or different type + + + + + `swappable`
+ `swappable_with` +
+
+ specifies that a type can be swapped or that two types can be swapped with each other +
+
+ From 1b8a92e130b5130a8c5b3b7fd404467d5bb2a4ed Mon Sep 17 00:00:00 2001 From: homodeluna <1402692684@qq.com> Date: Wed, 21 Jan 2026 02:18:52 +0800 Subject: [PATCH 7/7] feat(hash): update links --- src/content/docs/cpp/library/utility/hash.mdx | 64 ++++++++++++------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/src/content/docs/cpp/library/utility/hash.mdx b/src/content/docs/cpp/library/utility/hash.mdx index fa7f102a..c3148612 100644 --- a/src/content/docs/cpp/library/utility/hash.mdx +++ b/src/content/docs/cpp/library/utility/hash.mdx @@ -16,24 +16,42 @@ import { Card } from "@astrojs/starlight/components"; import FlexTable from "@components/FlexTable.astro"; - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,10 +74,10 @@ Given a type `Key`, each specialization `std::hash` is either _enabled_ or - If `std::hash` is not provided by the program or the user, it is disabled. - Otherwise, `std::hash` is enabled if all following conditions are satisfied: - All following requirements are satisfied: - - `Hash` (with `Key` as the function call argument type) - - `DefaultConstructible` - - [CopyAssignable](../named_req/CopyAssignable.html "cpp/named req/CopyAssignable") - - [Swappable](../named_req/Swappable.html "cpp/named req/Swappable") + - _Hash_ (with `Key` as the function call argument type) + - _DefaultConstructible_ + - _CopyAssignable_ + - _Swappable_ - Given the following values: - `h`, an object of type `std::hash`. @@ -210,7 +228,7 @@ int main() Possible outputs: -```cpp +``` hash("Meet the new boss...") = 10656026664466977650 hash("Hubert", "Farnsworth") = 12922914235676820612 (using MyHash) or 12922914235676820612 (using injected specialization)