Skip to content

Commit f220768

Browse files
authored
Revise spec for version 3.2 (#231)
1 parent f34bb8f commit f220768

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+868
-135
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.5)
22

3-
project(msft_proxy VERSION 3.1.0 LANGUAGES CXX)
3+
project(msft_proxy VERSION 3.2.0 LANGUAGES CXX)
44
add_library(msft_proxy INTERFACE)
55
target_compile_features(msft_proxy INTERFACE cxx_std_20)
66
target_include_directories(msft_proxy INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

README.md

+73-21
Large diffs are not rendered by default.

docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Macro `PRO_DEF_FREE_AS_MEM_DISPATCH`
22

33
```cpp
4-
#define PRO_DEF_FREE_AS_MEM_DISPATCH // see below
4+
#define PRO_DEF_FREE_AS_MEM_DISPATCH // since 3.1, see below
55
```
66
77
Macro `PRO_DEF_FREE_AS_MEM_DISPATCH` defines dispatch types for free function expressions with accessibility via a member function. It supports two syntaxes:
@@ -21,7 +21,7 @@ PRO_DEF_FREE_AS_MEM_DISPATCH(dispatch_name, func_name, accessibility_func_name);
2121
```cpp
2222
struct dispatch_name {
2323
template <class T, class... Args>
24-
decltype(auto) operator()(T&& self, Args&&... args)
24+
decltype(auto) operator()(T&& self, Args&&... args) const
2525
noexcept(noexcept(func_name(std::forward<T>(self), std::forward<Args>(args)...)))
2626
requires(requires { func_name(std::forward<T>(self), std::forward<Args>(args)...); }) {
2727
return func_name(std::forward<T>(self), std::forward<Args>(args)...);

docs/PRO_DEF_FREE_DISPATCH.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ PRO_DEF_FREE_DISPATCH(dispatch_name, func_name, accessibility_func_name);
2121
```cpp
2222
struct dispatch_name {
2323
template <class T, class... Args>
24-
decltype(auto) operator()(T&& self, Args&&... args)
24+
decltype(auto) operator()(T&& self, Args&&... args) const
2525
noexcept(noexcept(func_name(std::forward<T>(self), std::forward<Args>(args)...)))
2626
requires(requires { func_name(std::forward<T>(self), std::forward<Args>(args)...); }) {
2727
return func_name(std::forward<T>(self), std::forward<Args>(args)...);

docs/PRO_DEF_MEM_DISPATCH.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ PRO_DEF_MEM_DISPATCH(dispatch_name, func_name, accessibility_func_name);
2121
```cpp
2222
struct dispatch_name {
2323
template <class T, class... Args>
24-
decltype(auto) operator()(T&& self, Args&&... args)
24+
decltype(auto) operator()(T&& self, Args&&... args) const
2525
noexcept(noexcept(std::forward<T>(self).func_name(std::forward<Args>(args)...)))
2626
requires(requires { std::forward<T>(self).func_name(std::forward<Args>(args)...); }) {
2727
return std::forward<T>(self).func_name(std::forward<Args>(args)...);

docs/PRO_DEF_WEAK_DISPATCH.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Macro `PRO_DEF_WEAK_DISPATCH`
22

33
```cpp
4-
#define PRO_DEF_WEAK_DISPATCH // see below
4+
#define PRO_DEF_WEAK_DISPATCH // deprecated since 3.2, see below
55
```
66
7+
<mark>⚠️ Macro `PRO_DEF_WEAK_DISPATCH` has been replaced by class template `weak_dispatch` since 3.2, and may be removed in a future version.</mark>
8+
79
Macro `PRO_DEF_WEAK_DISPATCH` defines a "weak dispatch" type with a default implementation. It supports the following syntax:
810
911
```cpp
@@ -16,7 +18,7 @@ Defines a class named `dispatch_name` that inherits `existing_dispatch` and prov
1618
struct dispatch_name : existing_dispatch {
1719
using existing_dispatch::operator();
1820
template <class... Args>
19-
decltype(auto) operator()(std::nullptr_t, Args&&... args)
21+
decltype(auto) operator()(std::nullptr_t, Args&&... args) const
2022
noexcept(noexcept(default_func_name(std::forward<Args>(args)...)))
2123
requires(requires { default_func_name(std::forward<Args>(args)...); }) {
2224
return default_func_name(std::forward<Args>(args)...);
@@ -68,4 +70,5 @@ int main() {
6870

6971
## See Also
7072

73+
- [class template `weak_dispatch`](weak_dispatch.md)
7174
- [named requirements *ProDispatch*](ProDispatch.md)

docs/ProOverload.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ A type `O` meets the *ProOverload* requirements if it matches one of the followi
1212
| `R(Args...) && noexcept` |
1313
| `R(Args...) const` |
1414
| `R(Args...) const noexcept` |
15-
| `R(Args...) cosnt&` |
15+
| `R(Args...) const&` |
1616
| `R(Args...) const& noexcept` |
1717
| `R(Args...) const&&` |
1818
| `R(Args...) const&& noexcept` |

docs/access_proxy.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Accesses a `proxy` object from an [accessor](ProAccessible.md) instantiated from
1818
1919
## Return Value
2020
21-
A reference to the `proxy` that instantiates `a`.
21+
A reference to the `proxy` that has instantiated `a`.
2222
2323
## Notes
2424

docs/bad_proxy_cast.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Class `bad_proxy_cast`
2+
3+
```cpp
4+
class bad_proxy_cast : public std::bad_cast;
5+
```
6+
7+
A type of object to be thrown by the value-returning forms of [`proxy_cast`](basic_facade_builder/support_rtti.md) on failure.
8+
9+
## Member Functions
10+
11+
| Name | Description |
12+
| ------------- | ------------------------------------ |
13+
| (constructor) | constructs a `bad_proxy_cast` object |
14+
| (destructor) | destroys a `bad_proxy_cast` object |
15+
| `what` | returns the explanatory string |

docs/basic_facade_builder.md

+65-5
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,83 @@ using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
2525
2626
`class Cs`, `class Rs`, and `proxiable_ptr_constraints C` are the template parameters of `basic_facade_builder`. `basic_facade_builder` provides a member type `build` that compiles the template parameters into a [`facade`](facade.md) type. The template parameters can be modified via various member alias templates that specify `basic_facade_builder` with the modified template parameters.
2727
28+
## Notes
29+
30+
The design of `basic_facade_builder` utilizes template metaprogramming techniques. We recommend the following 2 guidelines when using `basic_facade_builder` to define a facade type.
31+
32+
- **Define a type for each facade.**
33+
34+
For example, when defining a `Formattable` facade, the following two definitions are both syntactically correct:
35+
36+
```cpp
37+
// (1) Recommended
38+
struct Formattable : pro::facade_builder
39+
::support_format
40+
::build {};
41+
42+
// (2) Discouraged
43+
using Formattable = pro::facade_builder
44+
::support_format
45+
::build;
46+
```
47+
48+
Definition `(2)` is a type alias, its "real" type may have a long name, and the type evaluation may be executed for multiple times even when compiling a single source file. Although the two type definitions are equivalent at runtime, definitions like `(2)` may significantly reduce compilation performance. Therefore, it is recommended always to define a facade as a type with inheritance, similar to definition `(1)`.
49+
50+
- **Use the `template` keyword on demand when defining a facade template.**
51+
52+
Consider the following facade template definitions:
53+
54+
```cpp
55+
template <class... Os>
56+
struct MovableCallable : pro::facade_builder
57+
::add_convention<pro::operator_dispatch<"()">, Os...>
58+
::build {};
59+
60+
template <class... Os>
61+
struct CopyableCallable : pro::facade_builder
62+
::add_facade<MovableCallable<Os...>>
63+
::support_copy<pro::constraint_level::nontrivial>
64+
::build {};
65+
```
66+
67+
Although GCC can usually compile the code above, it does not adhere to the C++ standard syntax, and as a result, it won't compile with Clang or MSVC ([live demo](https://godbolt.org/z/Gen74qY9r)). This is because type `add_facade<MovableCallable<Os...>>` depends on the template parameters, and an explicit `template` is required when specifying its member alias template `support_copy`. To fix the code, we could either add the keyword `template` before `support_copy`, or simply swap `add_facade` and `support_copy`. For instance:
68+
69+
```cpp
70+
template <class... Os>
71+
struct CopyableCallable : pro::facade_builder
72+
::add_facade<MovableCallable<Os...>>
73+
::template support_copy<pro::constraint_level::nontrivial>
74+
::build {};
75+
76+
// Or
77+
78+
template <class... Os>
79+
struct CopyableCallable : pro::facade_builder
80+
::support_copy<pro::constraint_level::nontrivial>
81+
::add_facade<MovableCallable<Os...>>
82+
::build {};
83+
```
84+
2885
## Member Types
2986

30-
| Name | Description |
31-
| ---------------------------------------- | ------------------------------------------------------------ |
32-
| [`build`](basic_facade_builder/build.md) | Specifies a [`facade`](facade.md) type deduced from the template parameters of the `basic_facade_builder` |
87+
| Name | Description |
88+
| ------------------------------------------------------------ | ------------------------------------------------------------ |
89+
| [`build`](basic_facade_builder/build.md) | Specifies a [`facade`](facade.md) type deduced from the template parameters of the `basic_facade_builder` |
90+
| [`support_format`<br />`support_wformat`](basic_facade_builder/support_format.md)<br />*(since 3.2)* | Specifies the capability of formatting (via [formatting functions](https://en.cppreference.com/w/cpp/utility/format)) to the template parameters |
91+
| [`support_rtti`<br />`support_indirect_rtti`<br />`support_direct_rtti`](basic_facade_builder/support_rtti.md)<br />*(since 3.2)* | Specifies the capability of RTTI (via `proxy_cast` and `proxy_typeid`) to the template parameters |
3392

3493
## Member Alias Templates
3594

3695
| Name | Description |
3796
| ------------------------------------------------------------ | ------------------------------------------------------------ |
3897
| [`add_convention`<br />`add_indirect_convention`<br />`add_direct_convention`](basic_facade_builder/add_convention.md) | Adds a convention to the template parameters |
39-
| [`add_reflection`<br />`add_indirect_reflection`<br />`add_direct_reflection`](basic_facade_builder/add_reflection.md) | Adds a reflection to the template parameters |
4098
| [`add_facade`](basic_facade_builder/add_facade.md) | Adds a facade to the template parameters |
99+
| [`add_reflection`<br />`add_indirect_reflection`<br />`add_direct_reflection`](basic_facade_builder/add_reflection.md) | Adds a reflection to the template parameters |
100+
| [`add_view` ](basic_facade_builder/support_view.md)<br />*(since 3.2)* | Specifies the capability of implicit conversion to `proxy_view` to the template parameters |
41101
| [`restrict_layout`](basic_facade_builder/restrict_layout.md) | Specifies maximum `max_size` and `max_align` of `C` in the template parameters |
42102
| [`support_copy`](basic_facade_builder/support_copy.md) | Specifies minimum `copyability` of `C` in the template parameters |
43-
| [`support_relocation`](basic_facade_builder/support_relocation.md) | Specifies minimum `relocatability` of `C` in the template parameters |
44103
| [`support_destruction`](basic_facade_builder/support_destruction.md) | Specifies minimum `destructibility` of `C` in the template parameters |
104+
| [`support_relocation`](basic_facade_builder/support_relocation.md) | Specifies minimum `relocatability` of `C` in the template parameters |
45105

46106
## Member Functions
47107

docs/basic_facade_builder/build.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using build = /* see below */;
55
```
66

7-
Specifies a [facade](facade.md) type deduced from the template parameters of `basic_facade_builder<Cs, Rs, C>`. Specifically,
7+
Specifies a [facade](../facade.md) type deduced from the template parameters of `basic_facade_builder<Cs, Rs, C>`. Specifically,
88

99
- `typename build::convention_types` is defined as `Cs`, and
1010
- `typename build::reflection_types` is defined as `Rs`, and
@@ -50,7 +50,7 @@ consteval proxiable_ptr_constraints normalize(proxiable_ptr_constraints value) {
5050
5151
It is encouraged to inherit `build` with an empty `struct` before specifying a [`proxy`](../proxy.md), rather than `using` or `typedef` the `build` type into an alias, to improve compilation performance.
5252
53-
The default values of the fields of [`proxiable_ptr_constraints`](../proxiable_ptr_constraints.md) are based on our engineering practices. The default values of `max_size` and `max_alignment` are usually sufficient for many implementations of [fancy pointers](https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers), such as [`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr), [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr), and [boost::interprocess::offset_ptr](https://www.boost.org/doc/libs/1_85_0/doc/html/interprocess/offset_ptr.html). A larger combination of size and alignment ensures better compatibility with the implementation of the underlying pointers and reduces heap allocation when the element type fits in the buffer (see [function template `make_proxy`](../make_proxy.md)), at the cost of making the corresponding [`proxy`](../proxy.md) objects larger.
53+
The default values of the fields of [`proxiable_ptr_constraints`](../proxiable_ptr_constraints.md) are based on our engineering practices. The default values of `max_size` and `max_alignment` are usually sufficient for many implementations of [fancy pointers](https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers), such as [`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr), [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr), and [`boost::interprocess::offset_ptr`](https://www.boost.org/doc/libs/1_85_0/doc/html/interprocess/offset_ptr.html). A larger combination of size and alignment ensures better compatibility with the implementation of the underlying pointers and reduces heap allocation when the element type fits in the buffer (see [function template `make_proxy`](../make_proxy.md)), at the cost of making the corresponding [`proxy`](../proxy.md) objects larger.
5454
5555
## Example
5656
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# `basic_facade_builder::support_format`<br />`basic_facade_builder::support_wformat`
2+
3+
```cpp
4+
using support_format = basic_facade_builder</* see below */>;
5+
6+
using support_wformat = basic_facade_builder</* see below */>;
7+
```
8+
9+
The member types `support_format` and `support_wformat` of `basic_facade_builder<Cs, Rs, C>` add necessary convention and reflection types to the template parameters, enabling specializations of [`std::formatter<proxy_indirect_accessor<F>, CharT>`](../formatter_proxy_indirect_accessor.md) where `F` is a [facade](../facade.md) type built from `basic_facade_builder`, `CharT` is `char` (if `support_format` is specified) or `wchar_t` (if `support_wformat` is specified).
10+
11+
`support_format` and `support_wformat` also add constraints to a facade type `F` built from `basic_facade_builder`, requiring a contained value of `proxy<F>` be *formattable*. Formally, let `p` be a contained value of `proxy<F>`, `CharT` be `char` (if `support_format` is specified) or `wchar_t` (if `support_wformat` is specified), `T` be `std::decay_t<decltype(*std::as_const(p))>`, `std::formatter<T, CharT>` shall be an enabled specialization of `std::formatter`.
12+
13+
## Example
14+
15+
```cpp
16+
#include <format>
17+
#include <iostream>
18+
19+
#include "proxy.h"
20+
21+
struct Formattable : pro::facade_builder
22+
::support_format
23+
::build {};
24+
25+
int main() {
26+
pro::proxy<Formattable> p = pro::make_proxy<Formattable>(123);
27+
std::cout << std::format("{}", *p) << "\n"; // Prints: "123"
28+
std::cout << std::format("{:*<6}", *p) << "\n"; // Prints: "123***"
29+
}
30+
```
31+
32+
## See Also
33+
34+
- [class template `std::formatter<proxy_indirect_accessor>`](../formatter_proxy_indirect_accessor.md)
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# `basic_facade_builder::support_rtti`<br />`basic_facade_builder::support_indirect_rtti`<br />`basic_facade_builder::support_direct_rtti`
2+
3+
```cpp
4+
using support_rtti = support_indirect_rtti;
5+
6+
using support_indirect_rtti = basic_facade_builder</* see below */>;
7+
8+
using support_direct_rtti = basic_facade_builder</* see below */>;
9+
```
10+
11+
The member types `support_rtti`, `support_indirect_rtti` and `support_direct_rtti` add necessary convention and reflection types to the template parameters, enabling [RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) support for [`proxy<F>`](../proxy.md), where `F` is a [facade](../facade.md) type built from `basic_facade_builder`. For an RTTI-enabled facade `F`, non-member functions `proxy_typeid` (similar to [`std::any::type`](https://en.cppreference.com/w/cpp/utility/any/type)) and `proxy_cast` (similar to [`std::any_cast`](https://en.cppreference.com/w/cpp/utility/any/any_cast)) are available for [`proxy_indirect_accessor<F>`](../proxy_indirect_accessor.md) (if `support_rtti` or `support_indirect_rtti` is specified) or [`proxy<F>`](../proxy.md) (if `support_direct_rtti` is specified).
12+
13+
## Non-Member Functions
14+
15+
| Name | Description |
16+
| ---------------------------------------------- | ------------------------------------------ |
17+
| [`proxy_typeid`](support_rtti/proxy_typeid.md) | returns the `typeid` of the contained type |
18+
| [`proxy_cast`](support_rtti/proxy_cast.md) | type-safe access to the contained object |
19+
20+
## Example
21+
22+
```cpp
23+
#include <iostream>
24+
25+
#include "proxy.h"
26+
27+
struct RttiAware : pro::facade_builder
28+
::support_rtti
29+
::support_direct_rtti
30+
::build {};
31+
32+
int main() {
33+
int v = 123;
34+
pro::proxy<RttiAware> p = &v;
35+
std::cout << proxy_typeid(p).name() << "\n"; // Prints: "Pi" (assuming GCC)
36+
std::cout << proxy_cast<int*>(p) << "\n"; // Prints the address of v
37+
std::cout << proxy_typeid(*p).name() << "\n"; // Prints: "i" (assuming GCC)
38+
std::cout << proxy_cast<int>(*p) << "\n"; // Prints: "123"
39+
}
40+
```
41+
42+
## See Also
43+
44+
- [`support_view`](support_view.md)

0 commit comments

Comments
 (0)