Skip to content

Commit

Permalink
Merge pull request #65 from bemanproject/constexpr_example
Browse files Browse the repository at this point in the history
Make sure constexpr functions are working under constexpr environment
  • Loading branch information
wusatosi authored Feb 6, 2025
2 parents 7355351 + 13eedc1 commit 8d385f1
Show file tree
Hide file tree
Showing 6 changed files with 440 additions and 16 deletions.
46 changes: 36 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ SPDX-License-Identifier: <SPDX License Expression>

# beman.inplace\_vector: Dynamically-resizable vector with fixed capacity

<!-- markdownlint-disable -->
<img src="https://github.com/bemanproject/beman/blob/main/images/logos/beman_logo-beman_library_under_development.png" style="width:5%; height:auto;"> ![Continuous Integration Tests](https://github.com/bemanproject/inplace_vector/actions/workflows/ci_tests.yml/badge.svg)
![Library Status](https://github.com/bemanproject/beman/blob/c6997986557ec6dda98acbdf502082cdf7335526/images/badges/beman_badge-beman_library_under_development.svg)
![Continuous Integration Tests](https://github.com/bemanproject/inplace_vector/actions/workflows/ci_tests.yml/badge.svg)
![Code Format](https://github.com/bemanproject/inplace_vector/actions/workflows/pre-commit.yml/badge.svg)
<!-- markdownlint-enable -->

**Implements**: [`inplace_vector` (P0843R14)](https://wg21.link/P0843R14)

<!-- markdownlint-disable -->
**Status**: [Under development and not yet ready for production use.](https://github.com/bemanproject/beman/blob/main/docs/BEMAN_LIBRARY_MATURITY_MODEL.md#under-development-and-not-yet-ready-for-production-use)
<!-- markdownlint-enable -->
**Status**:
[Under development and not yet ready for production use.](https://github.com/bemanproject/beman/blob/main/docs/BEMAN_LIBRARY_MATURITY_MODEL.md#under-development-and-not-yet-ready-for-production-use)

## Usage

Expand All @@ -30,13 +28,16 @@ which dynamic memory allocations are undesired.
#### Note on implementation progress

Current implementation implements all public interfaces defined in the paper.
However constexpr related functionalities are not tested and maybe broken.

There have been minor updates to the wording after the paper is accepted, notably [P3247](wg21.link/P3247).
There have been minor updates to the wording after the paper is accepted,
notably [P3247](wg21.link/P3247).
Which changes the requirements for constexpr support.
This will likely be preceded with [P3074](wg21.link/P3074).
These has not been implemented yet.

You can follow [this link](eel.is/c++draft/inplace.vector)
to checkout the status of `inplace_vector` in the latest draft.

Contributions are welcome.

### Code example
Expand All @@ -53,21 +54,46 @@ using namespace beman;
* Generates fibonacci sequence using inplace_vector.
* See: https://en.wikipedia.org/wiki/Fibonacci_sequence
*/
template <int Capacity> inplace_vector<int, Capacity> fibonacci_to(int num) {
template <int Capacity>
constexpr inplace_vector<int, Capacity> fibonacci_to(int num) {
assert(num < Capacity);

inplace_vector<int, Capacity> vec;

constexpr static std::array<int, 2> first_two{0, 1};
constexpr std::array<int, 2> first_two{0, 1};
for (auto i = 0; i <= num; ++i) {
auto new_val = i < 2 ? first_two[i] : vec[i - 1] + vec[i - 2];
vec.push_back(new_val);
}

return vec;
}

/*
* Check the result of the computation at compile time.
*/
constexpr bool check_5() {
auto got = fibonacci_to<10>(5);
constexpr inplace_vector<int, 10> correct{0, 1, 1, 2, 3, 5};
return got == correct;
}

static_assert(check_5());

```
### Note on constexpr support
Since `constexpr` requirements are actively changing,
you can use `beman::has_constexpr_support` to detect if our implementation
provide constexpr support for a specific specialization of `inplace_vector`.
Note this is not part of the standard Library and should not be relied on once
`constexpr` requirement stabilize.
Example Usage:
`static_assert(beman::has_constexpr_support<beman::inplace_vector<int, 5>>)`.
## How to Build
### Compiler support
Expand Down
16 changes: 14 additions & 2 deletions examples/fibonacci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ using namespace beman;
* Generates fibonacci sequence using inplace_vector.
* See: https://en.wikipedia.org/wiki/Fibonacci_sequence
*/
template <int Capacity> inplace_vector<int, Capacity> fibonacci_to(int num) {
template <int Capacity>
constexpr inplace_vector<int, Capacity> fibonacci_to(int num) {
assert(num < Capacity);

inplace_vector<int, Capacity> vec;

constexpr static std::array<int, 2> first_two{0, 1};
constexpr std::array<int, 2> first_two{0, 1};
for (auto i = 0; i <= num; ++i) {
auto new_val = i < 2 ? first_two[i] : vec[i - 1] + vec[i - 2];
vec.push_back(new_val);
Expand All @@ -24,6 +25,17 @@ template <int Capacity> inplace_vector<int, Capacity> fibonacci_to(int num) {
return vec;
}

/*
* Check the result of the computation at compile time.
*/
constexpr bool check_5() {
auto got = fibonacci_to<10>(5);
constexpr inplace_vector<int, 10> correct{0, 1, 1, 2, 3, 5};
return got == correct;
}

static_assert(check_5());

/**
* Expected program output:
*
Expand Down
12 changes: 10 additions & 2 deletions include/beman/inplace_vector/inplace_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ concept container_compatible_range =
std::ranges::input_range<Rng> &&
std::convertible_to<std::ranges::range_reference_t<Rng>, T>;

template <typename T, std::size_t N>
concept satify_constexpr = N == 0 || std::is_trivial_v<T>;

} // namespace beman::details::inplace_vector

// Types implementing the `inplace_vector`'s storage
Expand Down Expand Up @@ -425,13 +428,18 @@ template <class T, size_t N> struct non_trivial {
// Selects the vector storage.
template <class T, size_t N>
using storage_for = std::conditional_t<
N == 0, zero_sized<T>,
std::conditional_t<std::is_trivial_v<T>, trivial<T, N>, non_trivial<T, N>>>;
!satify_constexpr<T, N>, non_trivial<T, N>,
std::conditional_t<N == 0, zero_sized<T>, trivial<T, N>>>;

} // namespace beman::details::inplace_vector::storage

namespace beman {

template <typename IV>
concept has_constexpr_support =
details::inplace_vector::satify_constexpr<typename IV::value_type,
IV::capacity()>;

/// Dynamically-resizable fixed-N vector with inplace storage.
template <class T, size_t N>
struct inplace_vector
Expand Down
11 changes: 11 additions & 0 deletions tests/beman/inplace_vector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,14 @@ add_gtest(triviality)
add_gtest(constructors)
add_gtest(size_n_data)
add_gtest(erasure)

# constexpr test
add_executable(beman.inplace_vector.tests.constexpr constexpr.test.cpp)
target_link_libraries(
beman.inplace_vector.tests.constexpr
PRIVATE beman.inplace_vector
)
add_test(
NAME beman.inplace_vector.tests.constexpr
COMMAND beman.inplace_vector.tests.constexpr
)
8 changes: 6 additions & 2 deletions tests/beman/inplace_vector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ Not tested for now.
> then no `inplace_vector<T, N>` member functions are usable in
> constant expressions.
Not tested for now.
See [constexpr.test.cpp](constexpr.test.cpp),
note that this test suite only ensure functions are usable in a constexpr
environment.
The validity of those functions are tested in the main test suite.
This test also doesn't exhaustivly test constexpr functions' behavior
when exception throwing is expected.

#### 6.5 Bad alloc requirement

Expand Down Expand Up @@ -99,7 +104,6 @@ See [erasure.test.cpp](erasure.test.cpp)

## Known Issues/ Missed Tests

- Constexpr related functionalities.
- Emplacement minimal copy/ construction.
- Exception safety on mutation.

Expand Down
Loading

0 comments on commit 8d385f1

Please sign in to comment.