https://github.com/patrickroberts/pr
An assortment of standalone C++ utilities
https://github.com/patrickroberts/pr
Last synced: 7 months ago
JSON representation
An assortment of standalone C++ utilities
- Host: GitHub
- URL: https://github.com/patrickroberts/pr
- Owner: patrickroberts
- License: mit
- Created: 2025-01-12T02:29:58.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-04-11T05:17:48.000Z (8 months ago)
- Last Synced: 2025-04-11T06:25:19.172Z (8 months ago)
- Language: C++
- Homepage:
- Size: 65.4 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `pr`
An assortment of standalone C++ utilities
## [`include/pr/context.hpp`](include/pr/context.hpp)
Synopsis
```cpp
namespace pr {
template
concept /*storable*/ = std::same_as>;
template *storable*/ T>
inline thread_local constinit T * /*context*/ = nullptr;
template
concept /*makeable*/ =
/*storable*/> and not std::is_rvalue_reference_v;
template
class /*provider*/ {
using value_type = std::remove_reference_t;
// `mutable` prevents UB when `make_context` initializes a `const auto`
[[no_unique_address]] mutable T inner_; // exposition-only
value_type *outer_; // exposition-only
public:
template
requires std::constructible_from
explicit /*provider*/(ArgsT &&...args) noexcept(
std::is_nothrow_constructible_v);
/*provider*/(const /*provider*/ &) = delete;
/*provider*/(/*provider*/ &&) = delete;
~/*provider*/() noexcept;
};
template *makeable*/ T, class... ArgsT>
requires std::constructible_from
[[nodiscard]] auto make_context(ArgsT &&...args) noexcept(
std::is_nothrow_constructible_v) -> /*provider*/;
template
concept /*gettable*/ = /*storable*/>;
template *gettable*/ T>
[[nodiscard]] auto get_context() noexcept -> T *;
} // namespace pr
```
---
pr::make_context
```cpp
template *makeable*/ T, class... ArgsT>
requires std::constructible_from
[[nodiscard]] auto make_context(ArgsT &&...args) noexcept(
std::is_nothrow_constructible_v) -> /*provider*/;
```
Constructs and returns `/*provider*/`, whose constructor initializes its members as if by `inner_(std::forward(args)...), outer_(std::exchange(/*context*/, std::addressof(inner_)))`. Its destructor restores `/*context*/` to the value of `outer_`. `T` must be a cv-unqualified non-reference or lvalue-reference type, or the instantiation is ill-formed, which can result in substitution failure when the call appears in the immediate context of a template instantiation.
---
pr::get_context
```cpp
template *gettable*/ T>
[[nodiscard]] auto get_context() noexcept -> T *;
```
Returns `/*context*/`, whose value has been initialized by thread-local calls to `pr::make_context(...)` or `pr::make_context(...)`, or `nullptr` otherwise. `T` must be an optionally const-qualified non-reference type, or the instantiation is ill-formed, which can result in substitution failure when the call appears in the immediate context of a template instantiation.
## [`include/pr/shared_view.hpp`](include/pr/shared_view.hpp)
Synopsis
```cpp
namespace pr {
namespace ranges {
template
concept copyable_view = /* see description */;
template
requires std::is_object_v
class shared_view : public std::ranges::view_interface> {
std::shared_ptr base_; // exposition-only
public:
shared_view() requires std::default_initializable;
explicit shared_view(RangeT &&base);
auto base() const noexcept -> RangeT &;
auto begin() -> std::ranges::iterator_t;
auto end() -> std::ranges::sentinel_t;
};
namespace views {
inline constexpr /* unspecified */ shared = /* unspecified*/;
} // namespace views
} // namespace ranges
namespace views = ranges::views;
} // namespace pr
template
inline constexpr bool
std::ranges::enable_borrowed_range> =
std::ranges::enable_borrowed_range;
```
---
pr::ranges::copyable_view
#### Concept
```cpp
namespace pr::ranges {
template
concept copyable_view =
std::ranges::view and std::copyable;
}
```
The `pr::ranges::copyable_view` concept is a refinement of `std::ranges::view` for which `std::copyable` is satisfied.
---
pr::views::shared
#### Call signature
```cpp
template
requires /* see below */
constexpr auto shared(RangeT &&range) -> copyable_view auto;
```
Given an expression `e` of type `T`, the expression `pr::views::shared(e)` is expression-equivalent to:
- `std::views::all(e)`, if it is a well-formed expression and `std::views::all_t` models `std::copyable`;
- `pr::ranges::shared_view{e}` otherwise.
---
pr::ranges::shared_view
Data members
| Member object | Definition |
| ----------------- | ----------------------------------------------------------------------------- |
| `base_` (private) | A `std::shared_ptr` of the underlying range. (exposition-only member object*) |
Member functions
#### `pr::ranges::shared_view::shared_view`
| | |
| ------------------------------------------------------------ | -------- |
| `shared_view() requires std::default_initializable;` | (1) |
| `explicit shared_view(RangeT &&base);` | (2) |
Constructs a `shared_view`.
1) Default constructor. Initializes `base_` as if by `base_(std::make_shared())`.
2) Initializes the underlying `base_` with `std::make_shared(std::move(base))`.
---
#### `pr::ranges::shared_view::base`
| |
| ---------------------------------------- |
| `auto base() const noexcept -> RangeT &` |
Equivalent to `return *base_;`.
---
#### `pr::ranges::shared_view::begin`
| |
| -------------------------------------------------- |
| `auto begin() -> std::ranges::iterator_t;` |
Equivalent to `return std::ranges::begin(*base_);`.
---
#### `pr::ranges::shared_view::end`
| |
| ------------------------------------------------ |
| `auto end() -> std::ranges::iterator_t;` |
Equivalent to `return std::ranges::end(*base_);`.
Helper templates
```cpp
template
inline constexpr bool
std::ranges::enable_borrowed_range> =
std::ranges::enable_borrowed_range;
```
This specialization of `std::ranges::enable_borrowed_range` makes `shared_view` satisfy `borrowed_range` when the underlying range satisfies it.
## [`include/pr/simple.hpp`](include/pr/simple.hpp)
Synopsis
```cpp
namespace pr {
template
inline constexpr bool /*enable*/ = false;
template
concept trait = std::is_aggregate_v and std::is_empty_v and
/*enable*/;
template
concept /*interface*/ = /*enable*/;
template
concept /*inplace*/ = /*enable*/;
template
concept /*pointer*/ = /*enable*/;
template
concept /*small*/ = /*enable*/;
template
concept /*small*/ = /*inplace*/ or /*pointer*/ or /*small*/;
template
concept /*storable-to*/ = /*storage*/ and /* see below */;
template
concept /*table*/ = /*enable*/;
template
concept /*simple*/ = /*enable*/;
template
concept trait_of = pr::trait and /*simple*/ and
/*enable*/;
template
concept simplifies = pr::trait_of;
template
concept implements = not /*simple*/> and
pr::trait and Trait::template enable;
template
concept /*different-from*/ =
not std::same_as, std::remove_cvref_t>;
template
concept concrete = /*different-from*/ and
/*interface*/ and implements;
template
concept /*invocable-r*/ = std::is_invocable_r_v;
template
concept /*reference*/ = std::is_reference_v;
template
concept /*prvalue*/ = not /*reference*/;
template
concept /*inplace-storable-to*/ =
/*storage*/ and not /*pointer*/ and
/* see below */;
template
struct inplace_storage;
struct pointer_storage;
template
struct small_storage;
struct trait_base {};
template
struct interface;
struct move_constructs;
struct inplace_table;
struct pointer_table;
template *interface*/ Interface,
/*storage*/ Storage = pr::small_storage,
/*table*/ Table = pr::pointer_table>
class simple {
public:
using interface_type = Interface;
using storage_type = Storage;
using table_type = /* unspecified */;
private:
table_type m_table; // exposition-only
storage_type m_storage; // exposition-only
public:
template T, /*invocable-r*/ F>
requires /*inplace*/ and
/*inplace-storable-to*/
simple(std::in_place_type_t tag,
F &&func) noexcept(std::is_nothrow_invocable_r_v);
template T, /*invocable-r*/ F>
requires /*pointer*/ or /*small*/
constexpr simple(std::in_place_type_t tag,
F &&func) noexcept(std::is_nothrow_invocable_r_v and
/*reference*/);
template T, /*invocable-r*/ F>
requires /*small*/ and
/*inplace-storable-to*/ and /*prvalue*/
constexpr simple(std::in_place_type_t tag,
F &&func) noexcept(std::is_nothrow_invocable_r_v);
template T, typename... Args>
requires /*storable-to*/ and
std::constructible_from
constexpr simple(std::in_place_type_t tag, Args &&...args) noexcept(
std::is_nothrow_constructible_v and
/* see below */);
template T>
requires /*storable-to*/ and
std::constructible_from
constexpr simple(T &&object) noexcept(
std::is_nothrow_constructible_v and /* see below */);
template T>
requires /*pointer*/ or /*small*/
constexpr simple(std::unique_ptr &&ptr) noexcept;
simple(const simple &) = delete;
simple(simple &&) = delete;
auto operator=(const simple &) -> simple & = delete;
auto operator=(simple &&) -> simple & = delete;
constexpr auto operator[](pr::trait_of auto trait) const noexcept;
constexpr ~simple() noexcept(/*inplace*/);
};
} // namespace pr
```
Example
See it on [Compiler Explorer](https://godbolt.org/z/7d4MGh5E4)
```cpp
#include
struct copy_constructs : pr::trait_base {
template
static constexpr bool enable = true;
template T>
static constexpr auto fn(const T &object) -> T;
template T>
static constexpr auto fn(const T &object) -> T {
return T(object);
}
};
struct speaks : pr::trait_base {
template
static constexpr bool enable = requires(const T &object) {
{ object.speak() } -> std::convertible_to;
};
template T>
static constexpr auto fn(const T &object) -> std::string;
template T>
static constexpr auto fn(const T &object) -> std::string {
return object.speak();
}
};
class animal {
using interface_type = pr::interface;
pr::simple impl;
public:
template T>
constexpr animal(T &&object) : impl(std::forward(object)) {}
constexpr animal(const animal &other)
: impl(other.impl[copy_constructs{}](other.impl)) {}
constexpr auto speak() const -> std::string { return impl[speaks{}](impl); }
};
struct cow {
constexpr auto speak() const { return "moo"; }
};
struct pig {
constexpr auto speak() const { return "oink"; }
};
struct dog {
constexpr auto speak() const { return "woof"; }
};
// compiles with -std=c++26 using [p2738]
static_assert([] {
std::vector animals{cow{}, pig{}, dog{}};
return animals[0].speak() == "moo" and
animals[1].speak() == "oink" and
animals[2].speak() == "woof";
}());
```