Skip to content
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

Revise design of conversion_dispatch #212

Merged
merged 4 commits into from
Dec 9, 2024
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
16 changes: 1 addition & 15 deletions .github/workflows/bvt-gcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,13 @@ jobs:

- name: install gcc
run: |
sudo apt install -y gcc-11 g++-11 gcc-12 g++-12 gcc-13 g++-13 gcc-14 g++-14
sudo apt install -y gcc-13 g++-13 gcc-14 g++-14

- name: check compiler versions
run: |
g++-11 --version
g++-12 --version
g++-13 --version
g++-14 --version

- name: build and run test with gcc 11
run: |
cmake -B build-gcc-11 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Release
cmake --build build-gcc-11 -j
ctest --test-dir build-gcc-11 -j

- name: build and run test with gcc 12
run: |
cmake -B build-gcc-12 -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Release
cmake --build build-gcc-12 -j
ctest --test-dir build-gcc-12 -j

- name: build and run test with gcc 13
run: |
cmake -B build-gcc-13 -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13 -DCMAKE_BUILD_TYPE=Release
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ The "Proxy" library is a self-contained solution for runtime polymorphism in C++

| Family | Minimum version | Required flags |
| ---------- | --------------- | -------------- |
| GCC | 11.2 | -std=c++20 |
| GCC | 13.1 | -std=c++20 |
| Clang | 15.0.0 | -std=c++20 |
| MSVC | 19.30 | /std:c++20 |
| MSVC | 19.31 | /std:c++20 |
| NVIDIA HPC | 24.1 | -std=c++20 |

## Build and Run Tests with CMake
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
Expand Up @@ -32,7 +32,7 @@ struct dispatch_name {
accessor() = delete;
};
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_trivial_v<accessor<F, C, Os>> && ...))
requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, C, Os>> && ...))
struct accessor<F, C, Os...> : accessor<F, C, Os>... {
using accessor<F, C, Os>::accessibility_func_name ...;
};
Expand Down
2 changes: 1 addition & 1 deletion docs/PRO_DEF_FREE_DISPATCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct dispatch_name {
accessor() = delete;
};
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_trivial_v<accessor<F, C, Os>> && ...))
requires(sizeof...(Os) > 1u && (std::is_constructible_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> {
Expand Down
2 changes: 1 addition & 1 deletion docs/PRO_DEF_MEM_DISPATCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct dispatch_name {
accessor() = delete;
};
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_trivial_v<accessor<F, C, Os>> && ...))
requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, C, Os>> && ...))
struct accessor<F, C, Os...> : accessor<F, C, Os>... {
using accessor<F, C, Os>::accessibility_func_name ...;
};
Expand Down
3 changes: 1 addition & 2 deletions docs/basic_facade_builder/add_convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ struct BasicStringable : pro::facade_builder
struct Stringable : pro::facade_builder
::add_facade<BasicStringable>
::support_copy<pro::constraint_level::nontrivial>
::add_direct_convention<pro::conversion_dispatch<pro::proxy<BasicStringable>>,
pro::proxy<BasicStringable>() &&>
::add_direct_convention<pro::conversion_dispatch, pro::proxy<BasicStringable>() &&>
::build {};

int main() {
Expand Down
67 changes: 0 additions & 67 deletions docs/conversion_dispatch.md

This file was deleted.

30 changes: 0 additions & 30 deletions docs/conversion_dispatch/accessor.md

This file was deleted.

14 changes: 0 additions & 14 deletions docs/conversion_dispatch/operator_call.md

This file was deleted.

44 changes: 44 additions & 0 deletions docs/explicit_conversion_dispatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Class `explicit_conversion_dispatch`

```cpp
class explicit_conversion_dispatch;

using conversion_dispatch = explicit_conversion_dispatch;
```

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`.

## Member Functions

| Name | Description |
| ------------------------------------------------------------ | --------------------------------------------------- |
| (constructor) [nothrow] | constructs an `explicit_conversion_dispatch` object |
| [`operator()`](explicit_conversion_dispatch/operator_call.md) | invokes the dispatch |

## Member Types

| Name | Description |
| ------------------------------------------------------ | --------------------------------- |
| [`accessor`](explicit_conversion_dispatch/accessor.md) | provides accessibility to `proxy` |

## Example

```cpp
#include <iostream>

#include "proxy.h"

struct IntConvertible : pro::facade_builder
::add_convention<pro::conversion_dispatch, int() const>
::build {};

int main() {
pro::proxy<IntConvertible> p = pro::make_proxy<IntConvertible, short>(123); // p holds a short
std::cout << static_cast<int>(*p) << "\n"; // Prints: "123"
}
```

## See Also

- [class `implicit_conversion_dispatch`](implicit_conversion_dispatch.md)
- [class template `operator_dispatch`](operator_dispatch.md)
30 changes: 30 additions & 0 deletions docs/explicit_conversion_dispatch/accessor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Class template `explicit_conversion_dispatch::accessor`

```cpp
// (1)
template <class F, class C, class... Os>
struct accessor {
accessor() = delete;
};

// (2)
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, C, Os>> && ...))
struct accessor<F, C, Os...> : accessor<F, C, Os>... {
using accessor<F, C, Os>::operator return-type-of<Os>...;
};

// (3)
template <class F, class C>
struct accessor<F, C, T() cv ref noex> {
explicit operator T() cv ref noex;
};
```

Let `SELF` be `std::forward<accessor cv ref>(*this)`.

`(1)` The default implementation of `accessor` is not constructible.

`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor<F, C, Os>...` are default-constructible, inherits all `accessor<F, C, Os>...` types and `using` their `operator return-type-of<Os>`. `return-type-of<O>` denotes the *return type* of the overload type `O`.

`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke<C, T() cv ref noex>(access_proxy<F>(SELF))`.
8 changes: 8 additions & 0 deletions docs/explicit_conversion_dispatch/operator_call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# `explicit_conversion_dispatch::operator()`

```cpp
template <class T>
/* see below */ operator()(T&& value) noexcept;
```

Returns a value that is implicitly convertible to any type `U` with expression `U{std::forward<T>(value)}` when `T` is explicitly convertible to type `U`.
57 changes: 57 additions & 0 deletions docs/implicit_conversion_dispatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Class `implicit_conversion_dispatch`

```cpp
class explicit_conversion_dispatch;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implicit_conversion_dispatch?

```

Class `implicit_conversion_dispatch` models a [dispatch](ProDispatch.md) type for implicit type conversion expressions. It meets the [*ProAccessible* requirements](ProAccessible.md) of applicable types.

## Member Functions

| Name | Description |
| ------------------------------------------------------------ | --------------------------------------------------- |
| (constructor) [nothrow] | constructs an `implicit_conversion_dispatch` object |
| [`operator()`](implicit_conversion_dispatch/operator_call.md) | invokes the dispatch |

## Member Types

| Name | Description |
| ------------------------------------------------------ | --------------------------------- |
| [`accessor`](implicit_conversion_dispatch/accessor.md) | provides accessibility to `proxy` |

## Example

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

#include "proxy.h"

struct Runnable : pro::facade_builder
::add_convention<pro::operator_dispatch<"()">, void()>
::build {};

struct CopyableRunnable : pro::facade_builder
::support_copy<pro::constraint_level::nontrivial>
::add_facade<Runnable>
::add_direct_convention<pro::implicit_conversion_dispatch,
pro::proxy<Runnable>() const&, pro::proxy<Runnable>() &&>
::build {};

int main() {
pro::proxy<CopyableRunnable> p1 = pro::make_proxy<CopyableRunnable>(
[] { std::cout << "Lambda expression invoked\n"; });
auto p2 = p1; // Copy construction
pro::proxy<Runnable> p3 = p2; // Implicit conversion via const reference of pro::proxy<CopyableRunnable>
std::cout << std::boolalpha << p2.has_value() << "\n"; // Prints: "true"
// auto p4 = p3; // Won't compile because pro::proxy<Runnable> is not copy-constructible
pro::proxy<Runnable> p5 = std::move(p2); // Implicit conversion via rvalue reference of pro::proxy<CopyableRunnable>
std::cout << p2.has_value() << "\n"; // Prints: "false"
(*p5)(); // Prints: "Lambda expression invoked"
}
```

## See Also

- [class `explicit_conversion_dispatch`](explicit_conversion_dispatch.md)
- [class template `operator_dispatch`](operator_dispatch.md)
30 changes: 30 additions & 0 deletions docs/implicit_conversion_dispatch/accessor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Class template `implicit_conversion_dispatch::accessor`

```cpp
// (1)
template <class F, class C, class... Os>
struct accessor {
accessor() = delete;
};

// (2)
template <class F, class C, class... Os>
requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, C, Os>> && ...))
struct accessor<F, C, Os...> : accessor<F, C, Os>... {
using accessor<F, C, Os>::operator return-type-of<Os>...;
};

// (3)
template <class F, class C>
struct accessor<F, C, T() cv ref noex> {
operator T() cv ref noex;
};
```

Let `SELF` be `std::forward<accessor cv ref>(*this)`.

`(1)` The default implementation of `accessor` is not constructible.

`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor<F, C, Os>...` are default-constructible, inherits all `accessor<F, C, Os>...` types and `using` their `operator return-type-of<Os>`. `return-type-of<O>` denotes the *return type* of the overload type `O`.

`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an implicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke<C, T() cv ref noex>(access_proxy<F>(SELF))`.
mingxwa marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 8 additions & 0 deletions docs/implicit_conversion_dispatch/operator_call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# `implicit_conversion_dispatch::operator()`

```cpp
template <class T>
T&& operator()(T&& value) noexcept;
```

Returns `std::forward<T>(value)`.
2 changes: 1 addition & 1 deletion docs/operator_dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Let `self` be the operand of [`proxy`](proxy.md), and `other` and `others...` be

| Name | Description |
| -------------------------------------------------- | ---------------------------------------- |
| (constructor) [trivial] | constructs an `operator_dispatch` object |
| (constructor) [nothrow] | constructs an `operator_dispatch` object |
| [`operator()`](operator_dispatch/operator_call.md) | invokes the dispatch |

## Member Types
Expand Down
Loading