Skip to content

Improve documentation formatting #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 [class template `observer_facade`, alias template `proxy_view`](https://microsoft.github.io/proxy/docs/observer_facade.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::add_view`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_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
2 changes: 1 addition & 1 deletion docs/access_proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ A reference to the `proxy` that has instantiated `a`.

Similar to [`proxy_invoke`](proxy_invoke.md), this function can be used to implement the accessibility of `proxy`. If the facade type `F` is defined with the recommended facilities, it has full accessibility support. Specifically, when:

- the underlying dispatch type `typename C::dispatch_type` is defined via [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md), [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), or is a specialization of either [`operator_dispatch`](operator_dispatch.md) or [`conversion_dispatch`](conversion_dispatch.md), and
- the underlying dispatch type `typename C::dispatch_type` is defined via [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md), [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), or is a specialization of either [`operator_dispatch`](operator_dispatch.md) or [`conversion_dispatch`](explicit_conversion_dispatch.md), and
- the convention is defined via [`facade_builder`](basic_facade_builder.md).

## Example
Expand Down
2 changes: 1 addition & 1 deletion docs/basic_facade_builder/add_convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ int main() {
- [macro `PRO_DEF_MEM_DISPATCH`](../PRO_DEF_MEM_DISPATCH.md)
- [macro `PRO_DEF_FREE_DISPATCH`](../PRO_DEF_FREE_DISPATCH.md)
- [class template `operator_dispatch`](../operator_dispatch.md)
- [class template `conversion_dispatch`](../conversion_dispatch.md)
- [class `conversion_dispatch`](../explicit_conversion_dispatch.md)
- [macro `PRO_DEF_WEAK_DISPATCH`](../PRO_DEF_WEAK_DISPATCH.md)
49 changes: 35 additions & 14 deletions docs/basic_facade_builder/add_reflection.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,59 @@ Adding duplicate reflection types is well-defined, whether done directly via `ad
## Example

```cpp
#include <array>
#include <iostream>
#include <typeinfo>

#include "proxy.h"

class RttiReflector {
struct LayoutReflector {
public:
template <class T>
constexpr explicit RttiReflector(std::in_place_type_t<T>) : type_(typeid(T)) {}
constexpr explicit LayoutReflector(std::in_place_type_t<T>)
: Size(sizeof(T)), Align(alignof(T)) {}

template <class F, bool IsDirect, class R>
struct accessor {
const char* GetTypeName() const noexcept {
const RttiReflector& self = pro::proxy_reflect<IsDirect, R>(pro::access_proxy<F>(*this));
return self.type_.name();
friend std::size_t SizeOf(const std::conditional_t<IsDirect, pro::proxy<F>,
pro::proxy_indirect_accessor<F>>& self) noexcept {
const LayoutReflector& refl = pro::proxy_reflect<IsDirect, R>(pro::access_proxy<F>(self));
return refl.Size;
}

friend std::size_t AlignOf(const std::conditional_t<IsDirect, pro::proxy<F>,
pro::proxy_indirect_accessor<F>>& self) noexcept {
const LayoutReflector& refl = pro::proxy_reflect<IsDirect, R>(pro::access_proxy<F>(self));
return refl.Align;
}
};

private:
const std::type_info& type_;
std::size_t Size, Align;
};

struct RttiAware : pro::facade_builder
::add_direct_reflection<RttiReflector>
::add_indirect_reflection<RttiReflector>
struct LayoutAware : pro::facade_builder
::add_direct_reflection<LayoutReflector>
::add_indirect_reflection<LayoutReflector>
::build {};

int main() {
int a = 123;
pro::proxy<RttiAware> p = &a;
std::cout << p.GetTypeName() << "\n"; // Prints "Pi" (assuming GCC)
std::cout << p->GetTypeName() << "\n"; // Prints "i" (assuming GCC)
pro::proxy<LayoutAware> p = &a;
std::cout << SizeOf(p) << "\n"; // Prints sizeof(raw pointer)
std::cout << AlignOf(p) << "\n"; // Prints alignof(raw pointer)
std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int)
std::cout << AlignOf(*p) << "\n"; // Prints alignof(int)

p = pro::make_proxy<LayoutAware>(123); // SBO enabled
std::cout << SizeOf(p) << "\n"; // Prints sizeof(int)
std::cout << AlignOf(p) << "\n"; // Prints alignof(int)
std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int)
std::cout << AlignOf(*p) << "\n"; // Prints alignof(int)

p = pro::make_proxy<LayoutAware, std::array<char, 100>>(); // SBO disabled
std::cout << SizeOf(p) << "\n"; // Prints sizeof(raw pointer)
std::cout << AlignOf(p) << "\n"; // Prints alignof(raw pointer)
std::cout << SizeOf(*p) << "\n"; // Prints "100"
std::cout << AlignOf(*p) << "\n"; // Prints "1"
}
```

Expand Down
2 changes: 0 additions & 2 deletions docs/basic_facade_builder/add_view.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ Let `p` be a value of type `proxy<F>`, `ptr` be the contained value of `p` (if a
## Example

```cpp
#include <iomanip>
#include <iostream>
#include <string>

#include "proxy.h"

Expand Down
4 changes: 2 additions & 2 deletions docs/basic_facade_builder/support_rtti/proxy_cast.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ int main() {
std::cout << e.what() << "\n"; // Prints an explanatory string
}
int* ptr1 = proxy_cast<int>(&*p);
std::cout << std::boolalpha << ptr1 << "\n"; // Prints an address
std::cout << std::boolalpha << &v << "\n"; // Prints the same address as above
std::cout << ptr1 << "\n"; // Prints an address
std::cout << &v << "\n"; // Prints the same address as above
double* ptr2 = proxy_cast<double>(&*p);
std::cout << ptr2 << "\n"; // Prints "0"
}
Expand Down
2 changes: 1 addition & 1 deletion docs/proxy_invoke.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The behavior is undefined if `p` does not contain a value.

It is generally not recommended to call `proxy_invoke` directly. Using an [`accessor`](ProAccessible.md) is usually a better option with easier and more descriptive syntax. If the facade type `F` is defined with the recommended facilities, it has full accessibility support. Specifically, when

- `D` is defined via [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md), [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), or is a specialization of either [`operator_dispatch`](operator_dispatch.md) or [`conversion_dispatch`](conversion_dispatch.md), and
- `D` is defined via [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md), [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), or is a specialization of either [`operator_dispatch`](operator_dispatch.md) or [`conversion_dispatch`](explicit_conversion_dispatch.md), and
- the convention type `Conv` is defined via [`facade_builder`](basic_facade_builder.md).

## Example
Expand Down
49 changes: 35 additions & 14 deletions samples/basic_facade_builder/add_reflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,57 @@
// Licensed under the MIT License.
// This file contains example code from add_reflection.md.

#include <array>
#include <iostream>
#include <typeinfo>

#include "proxy.h"

class RttiReflector {
struct LayoutReflector {
public:
template <class T>
constexpr explicit RttiReflector(std::in_place_type_t<T>) : type_(typeid(T)) {}
constexpr explicit LayoutReflector(std::in_place_type_t<T>)
: Size(sizeof(T)), Align(alignof(T)) {}

template <class F, bool IsDirect, class R>
struct accessor {
const char* GetTypeName() const noexcept {
const RttiReflector& self = pro::proxy_reflect<IsDirect, R>(pro::access_proxy<F>(*this));
return self.type_.name();
friend std::size_t SizeOf(const std::conditional_t<IsDirect, pro::proxy<F>,
pro::proxy_indirect_accessor<F>>& self) noexcept {
const LayoutReflector& refl = pro::proxy_reflect<IsDirect, R>(pro::access_proxy<F>(self));
return refl.Size;
}

friend std::size_t AlignOf(const std::conditional_t<IsDirect, pro::proxy<F>,
pro::proxy_indirect_accessor<F>>& self) noexcept {
const LayoutReflector& refl = pro::proxy_reflect<IsDirect, R>(pro::access_proxy<F>(self));
return refl.Align;
}
};

private:
const std::type_info& type_;
std::size_t Size, Align;
};

struct RttiAware : pro::facade_builder
::add_direct_reflection<RttiReflector>
::add_indirect_reflection<RttiReflector>
struct LayoutAware : pro::facade_builder
::add_direct_reflection<LayoutReflector>
::add_indirect_reflection<LayoutReflector>
::build {};

int main() {
int a = 123;
pro::proxy<RttiAware> p = &a;
std::cout << p.GetTypeName() << "\n"; // Prints "Pi" (assuming GCC)
std::cout << p->GetTypeName() << "\n"; // Prints "i" (assuming GCC)
pro::proxy<LayoutAware> p = &a;
std::cout << SizeOf(p) << "\n"; // Prints sizeof(raw pointer)
std::cout << AlignOf(p) << "\n"; // Prints alignof(raw pointer)
std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int)
std::cout << AlignOf(*p) << "\n"; // Prints alignof(int)

p = pro::make_proxy<LayoutAware>(123); // SBO enabled
std::cout << SizeOf(p) << "\n"; // Prints sizeof(int)
std::cout << AlignOf(p) << "\n"; // Prints alignof(int)
std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int)
std::cout << AlignOf(*p) << "\n"; // Prints alignof(int)

p = pro::make_proxy<LayoutAware, std::array<char, 100>>(); // SBO disabled
std::cout << SizeOf(p) << "\n"; // Prints sizeof(raw pointer)
std::cout << AlignOf(p) << "\n"; // Prints alignof(raw pointer)
std::cout << SizeOf(*p) << "\n"; // Prints "100"
std::cout << AlignOf(*p) << "\n"; // Prints "1"
}
2 changes: 0 additions & 2 deletions samples/basic_facade_builder/add_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// Licensed under the MIT License.
// This file contains example code from add_view.md.

#include <iomanip>
#include <iostream>
#include <string>

#include "proxy.h"

Expand Down
4 changes: 2 additions & 2 deletions samples/basic_facade_builder/support_rtti/proxy_cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ int main() {
std::cout << e.what() << "\n"; // Prints an explanatory string
}
int* ptr1 = proxy_cast<int>(&*p);
std::cout << std::boolalpha << ptr1 << "\n"; // Prints an address
std::cout << std::boolalpha << &v << "\n"; // Prints the same address as above
std::cout << ptr1 << "\n"; // Prints an address
std::cout << &v << "\n"; // Prints the same address as above
double* ptr2 = proxy_cast<double>(&*p);
std::cout << ptr2 << "\n"; // Prints "0"
}