Skip to content

Commit

Permalink
Documentation for 3.0.0 (#160)
Browse files Browse the repository at this point in the history
* Documentation for Proxy 3

* Remove en-us directory

* Update doc for basic_facade_builder::add_facade

* readme
  • Loading branch information
mingxwa authored Sep 6, 2024
1 parent 1902fa2 commit e76e4ac
Show file tree
Hide file tree
Showing 52 changed files with 2,762 additions and 132 deletions.
262 changes: 130 additions & 132 deletions README.md

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions docs/PRO_DEF_FREE_DISPATCH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Macro `PRO_DEF_FREE_DISPATCH`

```cpp
#define PRO_DEF_FREE_DISPATCH // see below
```
Macro `PRO_DEF_FREE_DISPATCH` defines dispatch types for free function expressions with accessibility. It supports two syntaxes:
```cpp
// (1)
PRO_DEF_FREE_DISPATCH(dispatch_name, func_name);
// (2)
PRO_DEF_FREE_DISPATCH(dispatch_name, func_name, accessibility_func_name);
```

`(1)` Equivalent to `PRO_DEF_FREE_DISPATCH(dispatch_name, func_name, func_name);`

`(2)` Defines a class named `dispatch_name` of free function call expressions of `func_name` with accessibility. `dispatch_name` meets the [*ProAccessible*](ProAccessible.md) requirements of types `F`, `C`, and `Os...`, where `F` models concept [`facade`](facade.md), `C` is a tuple element type defined in `typename F::convention_types`, and each type `O` (possibly qualified with *cv ref noex*) in `Os...` is a tuple element type defined in `typename C::overload_types`. The functions provided by `typename dispatch_name::template accessor<F, C, Os...>` are named `accessibility_func_name` and can be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `accessor` is an associated class of the arguments. Let `SELF` be `std::forward<accessor cv ref>(self)`, effectively equivalent to:

```cpp
struct dispatch_name {
template <class T, class... Args>
decltype(auto) operator()(T&& self, Args&&... args)
noexcept(noexcept(func_name(std::forward<T>(self), std::forward<Args>(args)...)))
requires(requires { func_name(std::forward<T>(self), std::forward<Args>(args)...); }) {
return func_name(std::forward<T>(self), std::forward<Args>(args)...);
}

template <class F, class C, class... Os> struct accessor {
accessor() = delete;
};
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_trivial_v<accessor<F, C, Os>> && ...))
struct accessor<F, C, Os...> : accessor<F, C, Os>... {};
template <class F, class C, class R, class... Args>
struct accessor<F, C, R(Args...) cv ref noex> {
friend R accessibility_func_name(accessor cv ref self, Args... args) noex {
return pro::proxy_invoke<C>(pro::access_proxy<F>(SELF), std::forward<Args>(args)...);
}
};
};
```
## Example
```cpp
#include <iostream>
#include <string>
#include "proxy.h"
PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString);
struct Stringable : pro::facade_builder
::add_convention<FreeToString, std::string()>
::build {};
int main() {
pro::proxy<Stringable> p = pro::make_proxy<Stringable>(123);
std::cout << ToString(*p) << "\n"; // Prints: "123"
}
```

## See Also

- [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md)
- [alias template `basic_facade_builder::add_convention`](basic_facade_builder/add_convention.md)
73 changes: 73 additions & 0 deletions docs/PRO_DEF_MEM_DISPATCH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Macro `PRO_DEF_MEM_DISPATCH`

```cpp
#define PRO_DEF_MEM_DISPATCH // see below
```
Macro `PRO_DEF_MEM_DISPATCH` defines dispatch types for member function expressions with accessibility. It supports two syntaxes:
```cpp
// (1)
PRO_DEF_MEM_DISPATCH(dispatch_name, func_name);
// (2)
PRO_DEF_MEM_DISPATCH(dispatch_name, func_name, accessibility_func_name);
```

`(1)` Equivalent to `PRO_DEF_MEM_DISPATCH(dispatch_name, func_name, func_name);`

`(2)` Defines a class named `dispatch_name` of member function call expressions of `func_name` with accessibility. `dispatch_name` meets the [*ProAccessible*](ProAccessible.md) requirements of types `F`, `C`, and `Os...`, where `F` models concept [`facade`](facade.md), `C` is a tuple element type defined in `typename F::convention_types`, and each type `O` (possibly qualified with *cv, ref, noex*) in `Os...` is a tuple element type defined in `typename C::overload_types`. The member functions provided by `typename dispatch_name::template accessor<F, C, Os...>` are named `accessibility_func_name`. Let `SELF` be `std::forward<accessor cv ref>(*this)`, effectively equivalent to:

```cpp
struct dispatch_name {
template <class T, class... Args>
decltype(auto) operator()(T&& self, Args&&... args)
noexcept(noexcept(std::forward<T>(self).func_name(std::forward<Args>(args)...)))
requires(requires { std::forward<T>(self).func_name(std::forward<Args>(args)...); }) {
return std::forward<T>(self).func_name(std::forward<Args>(args)...);
}

template <class F, class C, class... Os>
struct accessor {
accessor() = delete;
};
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_trivial_v<accessor<F, C, Os>> && ...))
struct accessor<F, C, Os...> : accessor<F, C, Os>... {
using accessor<F, C, Os>::accessibility_func_name ...;
};
template <class F, class C, class R, class... Args>
struct accessor<F, C, R(Args...) cv ref noex> {
R accessibility_func_name(Args... args) cv ref noex {
return pro::proxy_invoke<C>(pro::access_proxy<F>(SELF), std::forward<Args>(args)...);
}
};
};
```
## Example
```cpp
#include <iostream>
#include <string>
#include <vector>
#include "proxy.h"
PRO_DEF_MEM_DISPATCH(MemAt, at);
struct Dictionary : pro::facade_builder
::add_convention<MemAt, std::string(int index) const>
::build {};
int main() {
std::vector<const char*> v{"hello", "world"};
pro::proxy<Dictionary> p = &v;
std::cout << p->at(1) << "\n"; // Prints: "world"
}
```

## See Also

- [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md)
- [alias template `basic_facade_builder::add_convention`](basic_facade_builder/add_convention.md)
69 changes: 69 additions & 0 deletions docs/PRO_DEF_WEAK_DISPATCH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Macro `PRO_DEF_WEAK_DISPATCH`

```cpp
#define PRO_DEF_WEAK_DISPATCH // see below
```
Macro `PRO_DEF_WEAK_DISPATCH` defines a "weak" dispatch type with a default implementation. It supports the following syntax:
```cpp
PRO_DEF_WEAK_DISPATCH(dispatch_name, existing_dispatch, default_func_name);
```

Defines a class named `dispatch_name` that inherits `existing_dispatch` and provides additional overloads of `operator()` calling `default_func_name`. Effectively equivalent to:

```cpp
struct dispatch_name : existing_dispatch {
using existing_dispatch::operator();
template <class... Args>
decltype(auto) operator()(std::nullptr_t, Args&&... args)
noexcept(noexcept(default_func_name(std::forward<Args>(args)...)))
requires(requires { default_func_name(std::forward<Args>(args)...); }) {
return default_func_name(std::forward<Args>(args)...);
}
};
```
## Notes
A weak dispatch can extend an existing dispatch with a default implementation. This is useful when instantiating a `proxy<F>` with a value that does not support some conventions defined by `F`. Similar with [`PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), `default_func_name` can be the name of an arbitrary function or anything that supports `()` syntax, including a constructor.
## Example
```cpp
#include <iostream>
#include <string>
#include <vector>
#include "proxy.h"
struct NotImplemented {
explicit NotImplemented(auto&&...) { throw std::runtime_error{ "Not implemented!" }; }
template <class T>
operator T() const noexcept { std::terminate(); } // Or std::unreachable() in C++23
};
PRO_DEF_MEM_DISPATCH(MemAt, at);
PRO_DEF_WEAK_DISPATCH(WeakMemAt, MemAt, NotImplemented);
struct WeakDictionary : pro::facade_builder
::add_convention<WeakMemAt, std::string(int index) const>
::build {};
int main() {
std::vector<const char*> v{"hello", "world"};
pro::proxy<WeakDictionary> p1 = &v;
std::cout << p1->at(1) << "\n"; // Prints: "world"
pro::proxy<WeakDictionary> p2 = pro::make_proxy<WeakDictionary>(123);
try {
p2->at(1);
} catch (const std::runtime_error& e) {
std::cout << e.what() << "\n"; // Prints: "Not implemented!"
}
}
```

## See Also

- [named requirements *ProDispatch*](ProDispatch.md)
11 changes: 11 additions & 0 deletions docs/ProAccessible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Named requirements: *ProAccessible*

Given that `F` is a type meeting the [*ProBasicFacade* requirements](ProBasicFacade.md), a type `T` meets the *ProAccessible* requirements of types `F, Args...`, if the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| ------------------------------------------- | ------------------------------------------------------------ |
| `typename T::template accessor<F, Args...>` | A type that provides accessibility to `proxy`. It shall be a trivial class type and not [final](https://en.cppreference.com/w/cpp/language/final). |

## See Also

- [class template `proxy`](proxy.md)
14 changes: 14 additions & 0 deletions docs/ProBasicConvention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Named requirements: *ProBasicConvention*

A type `C` meets the *ProBasicConvention* requirements if the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| ---------------------------- | ------------------------------------------------------------ |
| `C::is_direct` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type `bool`, specifying whether the convention applies to a pointer type itself (`true`), or the element type of a pointer type (`false`). |
| `typename C::dispatch_type` | A [trivial type](https://en.cppreference.com/w/cpp/named_req/TrivialType) that defines how the calls are forwarded to the concrete types. |
| `typename C::overload_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type of one or more distinct types `Os`. Each type `O` in `Os` shall meet the [*ProOverload* requirements](ProOverload.md). |

## See Also

- [*ProBasicFacade* requirements](ProBasicFacade.md)
- [*ProConvention* requirements](ProConvention.md)
13 changes: 13 additions & 0 deletions docs/ProBasicFacade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Named requirements: *ProBasicFacade*

A type `F` meets the *ProBasicFacade* requirements if the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| ------------------------------ | ------------------------------------------------------------ |
| `typename F::convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Cs`. Each type `C` in `Cs` shall meet the [*ProBasicConvention* requirements](ProBasicConvention.md). |
| `typename F::reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Rs`. Each type `R` in `Rs` shall define reflection on pointer types. |
| `F::constraints` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) of type [`proxiable_ptr_constraints`](proxiable_ptr_constraints.md) that defines constraints to pointer types. |

## See Also

- [concept `facade`](facade.md)
11 changes: 11 additions & 0 deletions docs/ProConvention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Named requirements: *ProConvention*

A type `C` meets the *ProConvention* requirements of a type `P` if `C` meets the [*ProBasicConvention* requirements](ProBasicConvention.md), and the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| ---------------------------- | ------------------------------------------------------------ |
| `typename C::overload_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains one or more distinct types `Os`. Each type `O` in `Os` shall meet the [*ProOverload* requirements](ProOverload.md), and<br />- when `C::is_direct` is `true`, `typename C::dispatch_type` shall meet the [*ProDispatch* requirements](ProDispatch.md) of `P` and `O`, <br />- or otherwise, when `C::is_direct` is `false`, let `QP` be a qualified reference type of `P` with the *cv ref* qualifiers defined by `O` (`QP` is an lvalue reference type if `O` does not define a *ref* qualifier), `qp` be a value of `QP`, `*std::forward<QP>(qp)` shall be well-formed, and `typename C::dispatch_type` shall meet the [*ProDispatch* requirements](ProDispatch.md) of `decltype(*std::forward<QP>(qp))` and `O`. |

## See Also

- [*ProFacade* requirements](ProFacade.md)
28 changes: 28 additions & 0 deletions docs/ProDispatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Named requirements: *ProDispatch*

A type `D` meets the *ProDispatch* requirements of types `T` and `O` if `D` is a [trivial type](https://en.cppreference.com/w/cpp/named_req/TrivialType), `O` meets the [*ProOverload* requirelemts](ProOverload.md), and the following expressions are well-formed and have the specified semantics (let `R` be return type of `O`, `Args...` be the argument types of `O`. `args...` denotes values of type `Args...`, `v` denotes a value of type `T`, `cv` denotes a value of type `const T`).

| Definitions of `O` | Expressions | Semantics |
| ----------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| `R(Args...)` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, v, std::forward<Args>(args)...)` | Invokes dispatch type `D` with an lvalue reference of type `T` and `args...`, may throw. |
| `R(Args...) noexcept` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, v, std::forward<Args>(args)...)` | Invokes dispatch type `D` with an lvalue reference of type `T` and `args...`, shall not throw. |
| `R(Args...) &` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, v, std::forward<Args>(args)...)` | Invokes dispatch type `D` with an lvalue reference of type `T` and `args...`, may throw. |
| `R(Args...) & noexcept` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, v, std::forward<Args>(args)...)` | Invokes dispatch type `D` with an lvalue reference of type `T` and `args...`, shall not throw. |
| `R(Args...) &&` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, std::move(v), std::forward<Args>(args)...)` | Invokes dispatch type `D` with a rvalue reference of type `T` and `args...`, may throw. |
| `R(Args...) && noexcept` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, std::move(v), std::forward<Args>(args)...)` | Invokes dispatch type `D` with a rvalue reference of type `T` and `args...`, shall not throw. |
| `R(Args...) const` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, cv, std::forward<Args>(args)...)` | Invokes dispatch type `D` with a const reference of type `T` and `args...`, may throw. |
| `R(Args...) const noexcept` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, cv, std::forward<Args>(args)...)` | Invokes dispatch type `D` with a const reference of type `T` and `args...`, shall not throw. |
| `R(Args...) cosnt&` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, cv, std::forward<Args>(args)...)`, or<br />`d(nullptr, std::forward<Args>(args)...)` | Invokes dispatch type `D` with a const reference of type `T` and `args...`, may throw. |
| `R(Args...) const& noexcept` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, cv, std::forward<Args>(args)...)` | Invokes dispatch type `D` with a const reference of type `T` and `args...`, shall not throw. |
| `R(Args...) const&&` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, std::move(cv), std::forward<Args>(args)...)` | Invokes dispatch type `D` with a const rvalue reference of type `T` and `args...`, may throw. |
| `R(Args...) const&& noexcept` | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, std::move(cv), std::forward<Args>(args)...)` | Invokes dispatch type `D` with a const rvalue reference of type `T` and `args...`, shall not throw. |

Or,

| Definitions of `O` | Expressions | Semantics |
| -------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| `R(Args...)` *cv ref noex* | [`INVOKE<R>`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, nullptr, std::forward<Args>(args)...)` | Invokes the dispatch type `D` with `nullptr` and `args...`, may or may not throw depending on `noex`. |

## See Also

- [*ProConvention* requirements](ProConvention.md)
13 changes: 13 additions & 0 deletions docs/ProFacade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Named requirements: *ProFacade*

A type `F` meets the *ProFacade* requirements of a type `P` if `F` meets the [*ProBasicFacade* requirements](ProBasicFacade.md), and `P` meets the requirements defined by [`F::constraints`](proxiable_ptr_constraints.md), and the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| ------------------------------ | ------------------------------------------------------------ |
| `typename F::convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Cs`. Each type `C` in `Cs` shall meet the [*ProConvention* requirements](ProConvention.md) of `P`. |
| `typename F::reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains any number of distinct types `Rs`. Each type `R` in `Rs` shall meet the [*ProReflection* requirements](ProReflection.md) of `P`. |

## See Also

- [concept `proxiable`](proxiable.md)
- [*ProBasicFacade* requirements](ProBasicFacade.md)
23 changes: 23 additions & 0 deletions docs/ProOverload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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*.

| Definitions of `O` |
| ----------------------------- |
| `R(Args...)` |
| `R(Args...) noexcept` |
| `R(Args...) &` |
| `R(Args...) & noexcept` |
| `R(Args...) &&` |
| `R(Args...) && noexcept` |
| `R(Args...) const` |
| `R(Args...) const noexcept` |
| `R(Args...) cosnt&` |
| `R(Args...) const& noexcept` |
| `R(Args...) const&&` |
| `R(Args...) const&& noexcept` |

## See Also

- [*ProConvention* requirements](ProConvention.md)
- [class template `std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function)
11 changes: 11 additions & 0 deletions docs/ProReflection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Named requirements: *ProReflection*

A type `R` meets the *ProReflection* requirements of a type `P` if the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| -------------------------- | ------------------------------------------------------------ |
| `R{std::in_place_type<P>}` | A [core constant expression](https://en.cppreference.com/w/cpp/language/constant_expression) that constructs a value of type `R`, reflecting implementation-defined metadata of type `P`. |

## See Also

[*ProFacade* requirements](ProFacade.md)
Loading

0 comments on commit e76e4ac

Please sign in to comment.