Skip to content

Commit

Permalink
Improve proxy_view and remove add_view
Browse files Browse the repository at this point in the history
  • Loading branch information
mingxwa committed Feb 17, 2025
1 parent fdfc2cb commit 1d3de9a
Show file tree
Hide file tree
Showing 29 changed files with 297 additions and 240 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ The "Proxy" library is a self-contained solution for runtime polymorphism in C++
- **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`.
- **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)).
- **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.
- **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::add_view`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_view.html) for more details.
- **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.
- **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.
- **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.
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/proxy_invocation_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace {

void BM_SmallObjectInvocationViaProxy(benchmark::State& state) {
auto data = GenerateSmallObjectInvocationProxyTestData();
std::vector<pro::proxy_view<const InvocationTestFacade>> views{data.begin(), data.end()};
std::vector<pro::proxy_view<InvocationTestFacade>> views{data.begin(), data.end()};
for (auto _ : state) {
for (auto& p : views) {
int result = p->Fun();
Expand Down Expand Up @@ -50,7 +50,7 @@ void BM_LargeObjectInvocationViaProxy(benchmark::State& state) {

void BM_LargeObjectInvocationViaProxyView(benchmark::State& state) {
auto data = GenerateLargeObjectInvocationProxyTestData();
std::vector<pro::proxy_view<const InvocationTestFacade>> views{data.begin(), data.end()};
std::vector<pro::proxy_view<InvocationTestFacade>> views{data.begin(), data.end()};
for (auto _ : state) {
for (auto& p : views) {
int result = p->Fun();
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/proxy_invocation_benchmark_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ PRO_DEF_MEM_DISPATCH(MemFun, Fun);

struct InvocationTestFacade : pro::facade_builder
::add_convention<MemFun, int() const>
::add_view<const InvocationTestFacade>
::support_view
::build{};

struct InvocationTestBase {
Expand Down
2 changes: 1 addition & 1 deletion docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Macro `PRO_DEF_FREE_AS_MEM_DISPATCH`

```cpp
#define PRO_DEF_FREE_AS_MEM_DISPATCH // since 3.1, see below
#define PRO_DEF_FREE_AS_MEM_DISPATCH // since 3.1.0, see below
```
Macro `PRO_DEF_FREE_AS_MEM_DISPATCH` defines dispatch types for free function expressions with accessibility via a member function. It supports two syntaxes:
Expand Down
2 changes: 1 addition & 1 deletion docs/PRO_DEF_WEAK_DISPATCH.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Macro `PRO_DEF_WEAK_DISPATCH`

```cpp
#define PRO_DEF_WEAK_DISPATCH // deprecated since 3.2, see below
#define PRO_DEF_WEAK_DISPATCH // deprecated since 3.2.0, see below
```
<mark>⚠️ Macro <code>PRO_DEF_WEAK_DISPATCH</code> has been replaced by class template <code>weak_dispatch</code> since 3.2, and may be removed in a future version.</mark>
Expand Down
4 changes: 3 additions & 1 deletion docs/ProOverload.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Named requirements: *ProOverload*

A type `O` meets the *ProOverload* requirements if it matches one of the following definitions, where `R` is the *return type*, `Args...` are the *argument types*.
A type `O` meets the *ProOverload* requirements if `substituted-overload<O, F>` matches one of the following definitions, where `F` is any type meeting the [*ProBasicFacade* requirements](ProBasicFacade.md), `R` is the *return type*, `Args...` are the *argument types*.

The exposition-only type `substituted-overload<O, F>` is `OT<F>` if `O` is a specialization of [`facade_aware_overload_t<OT>`](facade_aware_overload_t.md), or `O` otherwise.

| Definitions of `O` |
| ----------------------------- |
Expand Down
2 changes: 1 addition & 1 deletion docs/bad_proxy_cast.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Class `bad_proxy_cast`

```cpp
class bad_proxy_cast : public std::bad_cast;
class bad_proxy_cast : public std::bad_cast; // since 3.2.0
```
A type of object to be thrown by the value-returning forms of [`proxy_cast`](basic_facade_builder/support_rtti.md) on failure.
Expand Down
6 changes: 3 additions & 3 deletions docs/basic_facade_builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
| Name | Description |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| [`build`](basic_facade_builder/build.md) | Specifies a [`facade`](facade.md) type deduced from the template parameters of the `basic_facade_builder` |
| [`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 |
| [`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 |
| [`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 |
| [`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 |
| [`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 |
## Member Alias Templates
Expand All @@ -40,7 +41,6 @@ using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
| [`add_convention`<br />`add_indirect_convention`<br />`add_direct_convention`](basic_facade_builder/add_convention.md) | Adds a convention to the template parameters |
| [`add_facade`](basic_facade_builder/add_facade.md) | Adds a facade to the template parameters |
| [`add_reflection`<br />`add_indirect_reflection`<br />`add_direct_reflection`](basic_facade_builder/add_reflection.md) | Adds a reflection to the template parameters |
| [`add_view` ](basic_facade_builder/add_view.md)<br />*(since 3.2)* | Specifies the capability of implicit conversion to `proxy_view` to the template parameters |
| [`restrict_layout`](basic_facade_builder/restrict_layout.md) | Specifies maximum `max_size` and `max_align` of `C` in the template parameters |
| [`support_copy`](basic_facade_builder/support_copy.md) | Specifies minimum `copyability` of `C` in the template parameters |
| [`support_destruction`](basic_facade_builder/support_destruction.md) | Specifies minimum `destructibility` of `C` in the template parameters |
Expand Down
4 changes: 2 additions & 2 deletions docs/basic_facade_builder/add_convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ The alias templates `add_convention`, `add_indirect_convention`, and `add_direct
- `IC::is_direct` is `false`.
- `typename IC::dispatch_type` is `D`.
- `typename IC::overload_types` is a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type of distinct types in `Os`.
- `typename IC::template accessor<F>` is `typename D::template accessor<F, false, D, Os...>` if applicable.
- `typename IC::template accessor<F>` is `typename D::template accessor<F, false, D, `[`substituted-overload<Os, F>`](../ProOverload.md)`...>` if applicable.
- `add_direct_convention` merges an implementation-defined convention type `IC` into `Cs`, where:
- `IC::is_direct` is `true`.
- `typename IC::dispatch_type` is `D`.
- `typename IC::overload_types` is a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type of distinct types in `Os`.
- `typename IC::template accessor<F>` is `typename D::template accessor<F, true, D, Os...>` if applicable.
- `typename IC::template accessor<F>` is `typename D::template accessor<F, true, D, `[`substituted-overload<Os, F>`](../ProOverload.md)`...>` if applicable.
When `Cs` already contains a convention type `IC2` where `IC2::is_direct == IC::is_direct && std::is_same_v<typename IC2::dispatch_type, typename IC::dispatch_type>` is `true`, `Os` merges with `typename IC2::overload_types` and removes duplicates, and `std::tuple_size_v<Cs>` shall not change.
Expand Down
43 changes: 0 additions & 43 deletions docs/basic_facade_builder/add_view.md

This file was deleted.

4 changes: 2 additions & 2 deletions docs/basic_facade_builder/support_format.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# `basic_facade_builder::support_format`<br />`basic_facade_builder::support_wformat`

```cpp
using support_format = basic_facade_builder</* see below */>;
using support_format = basic_facade_builder</* see below */>; // since 3.2.0

using support_wformat = basic_facade_builder</* see below */>;
using support_wformat = basic_facade_builder</* see below */>; // since 3.2.0
```

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).
Expand Down
8 changes: 4 additions & 4 deletions docs/basic_facade_builder/support_rtti.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# `basic_facade_builder::support_rtti`<br />`basic_facade_builder::support_indirect_rtti`<br />`basic_facade_builder::support_direct_rtti`

```cpp
using support_rtti = support_indirect_rtti;
using support_rtti = support_indirect_rtti; // since 3.2.0

using support_indirect_rtti = basic_facade_builder</* see below */>;
using support_indirect_rtti = basic_facade_builder</* see below */>; // since 3.2.0

using support_direct_rtti = basic_facade_builder</* see below */>;
using support_direct_rtti = basic_facade_builder</* see below */>; // since 3.2.0
```

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).
Expand Down Expand Up @@ -41,4 +41,4 @@ int main() {
## See Also
- [`add_view`](add_view.md)
- [`support_view`](support_view.md)
41 changes: 41 additions & 0 deletions docs/basic_facade_builder/support_view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# `basic_facade_builder::support_view`

```cpp
using support_view = basic_facade_builder</* see below */>;
```

The member type `support_view` of `basic_facade_builder<Cs, Rs, C>` adds necessary convention types to allow implicit conversion from [`proxy`](../proxy.md)`<F>` to [`proxy_view`](../proxy_view.md)`<F>` where `F` is a [facade](../facade.md) type built from `basic_facade_builder`.

Let `p` be a value of type `proxy<F>`, `ptr` be the contained value of `p` (if any), the conversion from type `proxy<F>&` to type `proxy_view<F>` is equivalent to `return raw-ptr{std::addressof(*ptr)}` if `p` contains a value, or otherwise equivalent to `return nullptr`. `observer-ptr` is an exposition-only type that `*observer-ptr`, `*std::as_const(observer-ptr)`, `*std::move(observer-ptr)` and `*std::move(std::as_const(observer-ptr))` are equivalent to `*ptr`, `*std::as_const(ptr)`, `*std::move(ptr)` and `*std::move(std::as_const(ptr))`, respectively.

## Notes

`support_view` is useful when a certain context does not take ownership of a `proxy` object. Similar to [`std::unique_ptr::get`](https://en.cppreference.com/w/cpp/memory/unique_ptr/get), [`std::shared_ptr::get`](https://en.cppreference.com/w/cpp/memory/shared_ptr/get) and the [borrowing mechanism in Rust](https://doc.rust-lang.org/rust-by-example/scope/borrow.html).

## Example

```cpp
#include <iostream>

#include "proxy.h"

struct RttiAware : pro::facade_builder
::support_rtti
::support_view
::build {};

static_assert(!std::is_trivially_copyable_v<pro::proxy<RttiAware>>);
static_assert(std::is_trivially_copyable_v<pro::proxy_view<RttiAware>>);

int main() {
pro::proxy<RttiAware> p = pro::make_proxy<RttiAware>(123);
pro::proxy_view<RttiAware> pv = p;
proxy_cast<int&>(*pv) = 456; // Modifies the contained object of p
std::cout << proxy_cast<int>(*pv) << "\n"; // Prints "456"
std::cout << proxy_cast<int>(*p) << "\n"; // Prints "456"
}
```
## See Also
- [`add_convention`](add_convention.md)
4 changes: 2 additions & 2 deletions docs/explicit_conversion_dispatch.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Class `explicit_conversion_dispatch`

```cpp
class explicit_conversion_dispatch; // since 3.2
class explicit_conversion_dispatch; // since 3.2.0

using conversion_dispatch = explicit_conversion_dispatch; // since 3.2
using conversion_dispatch = explicit_conversion_dispatch; // since 3.2.0
```

Class `explicit_conversion_dispatch` models a [dispatch](ProDispatch.md) type for explicit type conversion expressions. It meets the [*ProAccessible* requirements](ProAccessible.md) of applicable types. `conversion_dispatch` is an alias of `explicit_conversion_dispatch`.
Expand Down
Loading

0 comments on commit 1d3de9a

Please sign in to comment.