Skip to content

Commit 02a7c59

Browse files
authored
Revise documentation for 3.3.0 (#272)
1 parent 4f8eda6 commit 02a7c59

39 files changed

+535
-79
lines changed

Diff for: CMakeLists.txt

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

3-
project(msft_proxy VERSION 3.2.1 LANGUAGES CXX)
3+
project(msft_proxy VERSION 3.3.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}>

Diff for: README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Please refer to the [Proxy's Frequently Asked Questions](https://microsoft.githu
3131

3232
### Hello World
3333

34-
Let's get started with the following "Hello World" example:
34+
Let's get started with the following "Hello World" example ([run](https://godbolt.org/z/jr81Poz83)):
3535

3636
```cpp
3737
#include <format>
@@ -80,7 +80,7 @@ Here is a step-by-step explanation:
8080
8181
### Hello World (Stream Version)
8282
83-
In the previous "Hello Word" example, we demonstrated how `proxy` could manage different types of objects and be formatted with `std::format`. While `std::format` is not the only option to print objects in C++, can we simply make `proxy` work with `std::cout`? The answer is "yes". The previous example is equivalent to the following implementation:
83+
In the previous "Hello Word" example, we demonstrated how `proxy` could manage different types of objects and be formatted with `std::format`. While `std::format` is not the only option to print objects in C++, can we simply make `proxy` work with `std::cout`? The answer is "yes". The previous example is equivalent to the following implementation ([run](https://godbolt.org/z/q1b14WGff)):
8484
8585
```cpp
8686
#include <iomanip>
@@ -136,7 +136,7 @@ In addition to the operator expressions demonstrated in the previous examples, t
136136
- [class template `pro::operator_dispatch`](https://microsoft.github.io/proxy/docs/operator_dispatch.html): Dispatch type for operator expressions.
137137
- [class `explicit_conversion_dispatch` (aka. `conversion_dispatch`)](https://microsoft.github.io/proxy/docs/explicit_conversion_dispatch.html) and [class `implicit_conversion_dispatch`](https://microsoft.github.io/proxy/docs/implicit_conversion_dispatch.html): Dispatch type for conversion expressions.
138138

139-
Note that some facilities are provided as macro, because C++ templates today do not support generating a function with an arbitrary name. Here is another example that makes member function call expressions polymorphic:
139+
Note that some facilities are provided as macro, because C++ templates today do not support generating a function with an arbitrary name. Here is another example that makes member function call expressions polymorphic ([run](https://godbolt.org/z/xcEeYrjnY)):
140140

141141
```cpp
142142
#include <iostream>
@@ -205,11 +205,13 @@ The "Proxy" library is a self-contained solution for runtime polymorphism in C++
205205
206206
- **Overloading**: [`facade_builder::add_convention`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_convention.html) is more powerful than demonstrated above. It can take any number of overload types (formally, any type meeting the [*ProOverload* requirements](https://microsoft.github.io/proxy/docs/ProOverload.html)) and perform standard overload resolution when invoking a `proxy`.
207207
- **Facade composition**: [`facade_builder::add_facade`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_facade.html) allows flexible composition of different abstractions.
208+
- **Concepts**: To facilitate template programming with "Proxy", 3 concepts are exported from a facade type. Namely, [`proxiable`](https://microsoft.github.io/proxy/docs/proxiable.html), [`proxiable_target`](https://microsoft.github.io/proxy/docs/proxiable_target.html) and [`inplace_proxiable_target`](https://microsoft.github.io/proxy/docs/inplace_proxiable_target.html).
208209
- **Allocator awareness**: [function template `allocate_proxy`](https://microsoft.github.io/proxy/docs/allocate_proxy.html) is able to create a `proxy` from a value with any custom allocator. In C++11, [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function) and [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task) had constructors that accepted custom allocators for performance tuning, but these were [removed in C++17](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0302r1.html) because "the semantics are unclear, and there are technical issues with storing an allocator in a type-erased context and then recovering that allocator later for any allocations needed during copy assignment". These issues do not apply to `allocate_proxy`.
209210
- **Configurable constraints**: [`facade_builder`](https://microsoft.github.io/proxy/docs/basic_facade_builder.html) provides full support for constraints configuration, including memory layout (by [`restrict_layout`](https://microsoft.github.io/proxy/docs/basic_facade_builder/restrict_layout.html)), copyability (by [`support_copy`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_copy.html)), relocatability (by [`support_relocation`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_relocation.html)), and destructibility (by [`support_destruction`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_destruction.html)).
210211
- **Reflection**: `proxy` supports type-based compile-time reflection for runtime queries. Please refer to [`facade_builder::add_reflection`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_reflection.html) and [function template `proxy_reflect`](https://microsoft.github.io/proxy/docs/proxy_reflect.html) for more details.
211-
- **Non-owning proxy**: Although `proxy` can manage the lifetime of an object effectively, similar to a smart pointer, we sometimes want to dereference it before passing to a non-owning context. This has been implemented as an extension since 3.2. Please refer to [alias template `proxy_view`, class template `observer_facade`](https://microsoft.github.io/proxy/docs/proxy_view.html) and [`facade_builder::support_view`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_view.html) for more details.
212+
- **Non-owning proxy**: Although `proxy` can manage the lifetime of an object effectively, similar to a smart pointer, we sometimes want to dereference it before passing to a non-owning context. This has been implemented as an extension since 3.2.0. Please refer to [function template `make_proxy_view`](https://microsoft.github.io/proxy/docs/make_proxy_view.html), [alias template `proxy_view`, class template `observer_facade`](https://microsoft.github.io/proxy/docs/proxy_view.html) and [`facade_builder::support_view`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_view.html) for more details.
212213
- **RTTI**: [RTTI (run-time type information)](https://en.wikipedia.org/wiki/Run-time_type_information) provides "weak" reflection capability in C++ since the last century. Although it is not as powerful as reflection in some other languages (like `Object.GetType()` in C# or `Object.getClass()` in Java), it offers the basic infrastructure for type-safe casting at runtime. Since 3.2, "RTTI for `proxy`" has been implemented as an extension and allows users to opt-in for each facade definition. Please refer to [`facade_builder::support_rtti`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_rtti.html) for more details.
214+
- **Shared and weak ownership**: Although `proxy` can be created from a [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr), extensions are available to create `proxy` objects with shared and weak ownership in a more efficient way since 3.3.0. Please refer to [function template `make_proxy_shared`](https://microsoft.github.io/proxy/docs/make_proxy_shared.html), [`allocate_proxy_shared`](https://microsoft.github.io/proxy/docs/allocate_proxy_shared.html), [alias template `weak_proxy`, class template `weak_facade`](https://microsoft.github.io/proxy/docs/weak_proxy.html) and [`facade_builder::support_weak`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_weak.html) for more details.
213215
- **Weak dispatch**: When an object does not implement a convention, and we do not want it to trigger a hard compile error, it is allowed to specify a [`weak_dispatch`](https://microsoft.github.io/proxy/docs/weak_dispatch.html) that throws when invoked.
214216
215217
## <a name="compiler-req">Minimum Requirements for Compilers</a>

Diff for: docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ struct dispatch_name {
2727
return func_name(std::forward<T>(self), std::forward<Args>(args)...);
2828
}
2929

30-
template <class F, class C, class... Os>
30+
template <class F, bool IsDirect, class D, class... Os>
3131
struct accessor {
3232
accessor() = delete;
3333
};
34-
template <class F, class C, class... Os>
35-
requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, C, Os>> && ...))
36-
struct accessor<F, C, Os...> : accessor<F, C, Os>... {
37-
using accessor<F, C, Os>::accessibility_func_name ...;
34+
template <class F, bool IsDirect, class D, class... Os>
35+
requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, IsDirect, D, Os>> && ...))
36+
struct accessor<F, IsDirect, D, Os...> : accessor<F, IsDirect, D, Os>... {
37+
using accessor<F, IsDirect, D, Os>::accessibility_func_name ...;
3838
};
39-
template <class F, class C, class R, class... Args>
40-
struct accessor<F, C, R(Args...) cv ref noex> {
39+
template <class F, bool IsDirect, class D, class R, class... Args>
40+
struct accessor<F, IsDirect, D, R(Args...) cv ref noex> {
4141
R accessibility_func_name(Args... args) cv ref noex {
42-
return pro::proxy_invoke<C, R(Args...) cv ref noex>(pro::access_proxy<F>(std::forward<accessor cv ref>(*this)), std::forward<Args>(args)...);
42+
return pro::proxy_invoke<IsDirect, D, R(Args...) cv ref noex>(pro::access_proxy<F>(std::forward<accessor cv ref>(*this)), std::forward<Args>(args)...);
4343
}
4444
};
4545
}

Diff for: docs/ProReflection.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ A type `R` meets the *ProReflection* requirements of a type `P` if `R` meets the
88

99
## See Also
1010

11-
[*ProFacade* requirements](ProFacade.md)
11+
- [*ProFacade* requirements](ProFacade.md)

Diff for: docs/access_proxy.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
# Function template `access_proxy`
22

33
```cpp
4-
template <class F, class A>
4+
template <facade F, class A>
55
proxy<F>& access_proxy(A& a) noexcept;
66

7-
template <class F, class A>
7+
template <facade F, class A>
88
const proxy<F>& access_proxy(const A& a) noexcept;
99

10-
template <class F, class A>
10+
template <facade F, class A>
1111
proxy<F>&& access_proxy(A&& a) noexcept;
1212

13-
template <class F, class A>
13+
template <facade F, class A>
1414
const proxy<F>&& access_proxy(const A&& a) noexcept;
1515
```
1616
17-
Accesses a `proxy` object from an [accessor](ProAccessible.md) instantiated from the `proxy`. `F` shall model concept [`facade`](facade.md). As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing distinct types `Cs`. There shall be a type `C` in `Cs` where `A` is the same type as `typename C::template accessor<F>`. The behavior is undefined if `a` is not instantiated from a `proxy`.
17+
Accesses a `proxy` object from an [accessor](ProAccessible.md) instantiated from the `proxy`. As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing distinct types `Cs`. There shall be a type `C` in `Cs` where `A` is the same type as `typename C::template accessor<F>`. The behavior is undefined if `a` is not instantiated from a `proxy`.
1818
1919
## Return Value
2020

Diff for: docs/allocate_proxy.md

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ proxy<F> allocate_proxy(const Alloc& alloc, T&& value); // freestanding-deleted
2222
2323
`(3)` Creates a `proxy<F>` object containing a value `p` of type `allocated-ptr<std::decay_t<T>, Alloc>`, where `*p` is direct-non-list-initialized with `std::forward<T>(value)`.
2424
25+
*Since 3.3.0*: For `(1-3)`, if [`proxiable_target<std::decay_t<T>, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
26+
2527
## Return Value
2628
2729
The constructed `proxy` object.

Diff for: docs/allocate_proxy_shared.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Function template `allocate_proxy_shared`
2+
3+
The definition of `allocate_proxy_shared` makes use of exposition-only class templates *strong-compact-ptr* and *weak-compact-ptr*. Their semantics are similar to [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr) and [`std::weak_ptr`](https://en.cppreference.com/w/cpp/memory/weak_ptr), but do not provide a polymorphic deleter. Their size and alignment are guaranteed not to be greater than those of a raw pointer type. `strong-compact-ptr<T, Alloc>` is conditionally convertible to `weak-compact-ptr<T, Alloc>` only if necessary. Similar to [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional), `strong-compact-ptr<T, Alloc>` provides `operator*` for accessing the managed object of type `T` with the same qualifiers.
4+
5+
```cpp
6+
// (1)
7+
template <facade F, class T, class Alloc, class... Args>
8+
proxy<F> allocate_proxy_shared(const Alloc& alloc, Args&&... args); // freestanding-deleted
9+
10+
// (2)
11+
template <facade F, class T, class Alloc, class U, class... Args>
12+
proxy<F> allocate_proxy_shared(const Alloc& alloc, std::initializer_list<U> il, Args&&... args); // freestanding-deleted
13+
14+
// (3)
15+
template <facade F, class Alloc, class T>
16+
proxy<F> allocate_proxy_shared(const Alloc& alloc, T&& value); // freestanding-deleted
17+
```
18+
19+
`(1)` Creates a `proxy<F>` object containing a value `p` of type `strong-compact-ptr<T, Alloc>`, where `*p` is direct-non-list-initialized with `std::forward<Args>(args)...`.
20+
21+
`(2)` Creates a `proxy<F>` object containing a value `p` of type `strong-compact-ptr<T, Alloc>`, where `*p` is direct-non-list-initialized with `il, std::forward<Args>(args)...`.
22+
23+
`(3)` Creates a `proxy<F>` object containing a value `p` of type `strong-compact-ptr<std::decay_t<T>, Alloc>`, where `*p` is direct-non-list-initialized with `std::forward<T>(value)`.
24+
25+
For `(1-3)`, if [`proxiable_target<std::decay_t<T>, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
26+
27+
## Return Value
28+
29+
The constructed `proxy` object.
30+
31+
## Exceptions
32+
33+
Throws any exception thrown by allocation or the constructor of `T`.
34+
35+
## Notes
36+
37+
The implementation of `strong-compact-ptr` may vary depending on the definition of `F`. Specifically, when `F` does not support weak ownership via [`basic_facade_builder::support_weak`](basic_facade_builder/support_weak.md), `strong-compact-ptr<T, Alloc>` is not convertible to `weak-compact-ptr<T, Alloc>`, which leaves more room for optimization.
38+
39+
## Example
40+
41+
```cpp
42+
#include <iostream>
43+
#include <memory_resource>
44+
45+
#include "proxy.h"
46+
47+
struct RttiAware : pro::facade_builder
48+
::support_copy<pro::constraint_level::nothrow>
49+
::support_rtti
50+
::build {};
51+
52+
int main() {
53+
std::pmr::unsynchronized_pool_resource pool;
54+
std::pmr::polymorphic_allocator<> alloc{&pool};
55+
pro::proxy<RttiAware> p1 = pro::allocate_proxy_shared<RttiAware>(alloc, 1);
56+
pro::proxy<RttiAware> p2 = p1;
57+
proxy_cast<int&>(*p1) += 2;
58+
std::cout << proxy_cast<int>(*p2) << "\n"; // Prints "3"
59+
}
60+
```
61+
62+
## See Also
63+
64+
- [function template `allocate_proxy`](allocate_proxy.md)
65+
- [named requirements *Allocator*](https://en.cppreference.com/w/cpp/named_req/Allocator)

Diff for: docs/basic_facade_builder.md

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
3333
| [`support_format`<br />`support_wformat`](basic_facade_builder/support_format.md)<br />*(since 3.2.0)* | Specifies the capability of formatting (via [formatting functions](https://en.cppreference.com/w/cpp/utility/format)) to the template parameters |
3434
| [`support_rtti`<br />`support_indirect_rtti`<br />`support_direct_rtti`](basic_facade_builder/support_rtti.md)<br />*(since 3.2.0)* | Specifies the capability of RTTI (via `proxy_cast` and `proxy_typeid`) to the template parameters |
3535
| [`support_view` ](basic_facade_builder/support_view.md)<br />*(since 3.2.1)* | Specifies the capability of implicit conversion to `proxy_view` to the template parameters |
36+
| [`support_weak`](basic_facade_builder/support_weak.md)<br />*(since 3.3.0)* | Specifies the capability of implicit conversion to `weak_proxy` to the template parameters |
3637
3738
## Member Alias Templates
3839

Diff for: docs/basic_facade_builder/support_weak.md

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# `basic_facade_builder::support_weak`
2+
3+
```cpp
4+
using support_weak = basic_facade_builder</* see below */>;
5+
```
6+
7+
The member type `support_weak` of `basic_facade_builder<Cs, Rs, C>` adds necessary convention types to allow implicit conversion from [`proxy`](../proxy.md)`<F>` to [`weak_proxy`](../weak_proxy.md)`<F>` where `F` is a [facade](../facade.md) type built from `basic_facade_builder`.
8+
9+
Let `p` be a value of type `proxy<F>`, `ptr` of type `P` be the contained value of `p` (if any), the conversion from type `const proxy<F>&` to type `weak_proxy<F>` is equivalent to `return typename P::weak_type{ptr}` if `p` contains a value, or otherwise equivalent to `return nullptr`.
10+
11+
## Notes
12+
13+
`support_weak` is compatible with [`std::weak_ptr`](https://en.cppreference.com/w/cpp/memory/weak_ptr), and may generate more efficient code when working with [`make_proxy_shared`](../make_proxy_shared.md) or [`allocate_proxy_shared`](../allocate_proxy_shared.md). It is also compatible with any custom shared/weak ownership implementations if `typename P::weak_type{ptr}` is well-formed.
14+
15+
## Example
16+
17+
```cpp
18+
#include <iostream>
19+
20+
#include "proxy.h"
21+
22+
struct Formattable : pro::facade_builder
23+
::support_format
24+
::support_weak
25+
::build {};
26+
27+
int main() {
28+
pro::proxy<Formattable> p1 = pro::make_proxy_shared<Formattable>(123);
29+
pro::weak_proxy<Formattable> wp = p1;
30+
pro::proxy<Formattable> p2 = wp.lock();
31+
std::cout << std::boolalpha << p2.has_value() << "\n"; // Prints "true"
32+
std::cout << std::format("{}\n", *p2); // Prints "123"
33+
34+
p1.reset();
35+
p2.reset();
36+
p2 = wp.lock();
37+
std::cout << p2.has_value() << "\n"; // Prints "false"
38+
}
39+
```
40+
41+
## See Also
42+
43+
- [`add_convention`](add_convention.md)

Diff for: docs/facade_aware_overload_t.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Class template `facade_aware_overload_t<O>` specifies a facade-aware overload te
2121
template <class F>
2222
using BinaryOverload = pro::proxy<F>(const pro::proxy_indirect_accessor<F>& rhs) const;
2323
24-
template <class T, class F>
24+
template <class T, pro::facade F>
2525
pro::proxy<F> operator+(const T& value, const pro::proxy_indirect_accessor<F>& rhs)
2626
requires(!std::is_same_v<T, pro::proxy_indirect_accessor<F>>)
2727
{ return pro::make_proxy<F, T>(value + proxy_cast<const T&>(rhs)); }

Diff for: docs/formatter_proxy_indirect_accessor.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
```cpp
44
namespace std {
5-
template <class F, class CharT> requires(/* see below */)
5+
template <facade F, class CharT> requires(/* see below */)
66
struct formatter<pro::proxy_indirect_accessor<F>, ChatT>; // since 3.2.0
77
}
88
```

Diff for: docs/implicit_conversion_dispatch.md

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Class `implicit_conversion_dispatch` models a [dispatch](ProDispatch.md) type fo
2222
## Example
2323

2424
```cpp
25-
#include <iomanip>
2625
#include <iostream>
2726

2827
#include "proxy.h"

Diff for: docs/inplace_proxiable_target.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
```cpp
44
template <class T, class F>
5-
concept inplace_proxiable_target = proxiable</* inplace-ptr<T> */, F>;
5+
concept inplace_proxiable_target = proxiable<inplace-ptr<T>, F>;
66
```
77
8-
The concept `inplace_proxiable_target<T, F>` specifies that a value type `T`, when wrapped by an implementation-defined non-allocating pointer type, models a contained value type of [`proxy<F>`](proxy.md). The size and alignment of this implementation-defined pointer type are guaranteed to be equal to those of type `T`.
8+
See [`make_proxy_inplace`](make_proxy_inplace.md) for the definition of the exposition-only class template *inplace-ptr*.
99
1010
## Example
1111
@@ -31,4 +31,4 @@ int main() {
3131
## See Also
3232

3333
- [concept `proxiable`](proxiable.md)
34-
- [function template `make_proxy_inplacce`](make_proxy_inplace.md)
34+
- [concept `proxiable_target`](proxiable_target.md)

0 commit comments

Comments
 (0)