Skip to content
Open
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
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ option(
OFF
)

# Enable P3698
option(
BEMAN_INPLACE_VECTOR_CROSS_CAPACITY_COMPARISON
"Enable comparison operators between vectors of different capacities. Default: OFF. Values: { ON, OFF }."
OFF
)

configure_file(
"${PROJECT_SOURCE_DIR}/include/beman/inplace_vector/config_generated.hpp.in"
"${PROJECT_BINARY_DIR}/include/beman/inplace_vector/config_generated.hpp"
Expand Down
1 change: 1 addition & 0 deletions include/beman/inplace_vector/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <beman/inplace_vector/config_generated.hpp>
#else
#define BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS() 0
#define BEMAN_INPLACE_VECTOR_CROSS_CAPACITY_COMPARISON() 0
#endif

#endif
1 change: 1 addition & 0 deletions include/beman/inplace_vector/config_generated.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
#define BEMAN_INPLACE_VECTOR_CONFIG_GENERATED_HPP

#cmakedefine01 BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS()
#cmakedefine01 BEMAN_INPLACE_VECTOR_CROSS_CAPACITY_COMPARISON()

#endif
54 changes: 49 additions & 5 deletions include/beman/inplace_vector/inplace_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
}

// [containers.sequences.inplace_vector.data], data access

constexpr T *data() noexcept { return storage_data(); }
constexpr const T *data() const noexcept { return storage_data(); }

Expand Down Expand Up @@ -398,11 +399,6 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
}
}

constexpr friend bool operator==(const inplace_vector_base &x,
const inplace_vector_base &y) {
return x.size() == y.size() && std::ranges::equal(x, y);
}

Comment on lines -401 to -405

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you add a macro to selectively enable P3698?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Just added!

constexpr void swap(inplace_vector_base &x) noexcept(
N == 0 || (std::is_nothrow_swappable_v<T> &&
std::is_nothrow_move_constructible_v<T>))
Expand All @@ -420,6 +416,50 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
x.swap(y);
}

// [inplace.vector.comparison], comparison

#if BEMAN_INPLACE_VECTOR_CROSS_CAPACITY_COMPARISON()
template <std::size_t M>
constexpr friend bool operator==(const inplace_vector_base &x,
const inplace_vector_base<T, M> &y) {
const auto sz = std::min(x.size(), y.size());

return x.size() == y.size() &&
std::ranges::equal(x.begin(), x.begin() + sz, y.begin(),
y.begin() + sz);
}

template <std::size_t M>
requires std::three_way_comparable<T> || lessthan_comparable<T>
constexpr friend auto operator<=>(const inplace_vector_base &x,
const inplace_vector_base<T, M> &y) {
using result_t = std::conditional_t<std::three_way_comparable<T>,
std::compare_three_way_result<T>,
std::strong_ordering>;

if constexpr (std::three_way_comparable<T>) {
return std::lexicographical_compare_three_way(
x.begin(), x.end(), y.begin(), y.end(), std::compare_three_way());
} else {
const auto sz = std::min(x.size(), y.size());

for (std::size_t i = 0; i < sz; ++i) {
if (x[i] < y[i])
return result_t::less;
if (y[i] < x[i])
return result_t::greater;
// [container.opt.reqmts] < must be total ordering relationship
}

return x.size() <=> y.size();
}
}
#else
constexpr friend bool operator==(const inplace_vector_base &x,
const inplace_vector_base &y) {
return x.size() == y.size() && std::ranges::equal(x, y);
}

constexpr friend auto operator<=>(const inplace_vector_base &x,
const inplace_vector_base &y)
requires(details::lessthan_comparable<T>)
Expand All @@ -441,6 +481,8 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
}
}

#endif

// [containers.sequences.inplace_vector.cons], construct/copy/destroy

constexpr inplace_vector_base() noexcept = default;
Expand Down Expand Up @@ -925,6 +967,8 @@ struct inplace_vector : public details::inplace_vector_base<T, N> {

} // namespace freestanding

// [inplace.vector.erasure], erasure

template <typename T, std::size_t N, typename U = T>
constexpr std::size_t erase(details::inplace_vector_base<T, N> &c,
const U &value) {
Expand Down
26 changes: 13 additions & 13 deletions tests/beman/inplace_vector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

find_package(GTest REQUIRED)

# Tests
# External test suite from @Hels15
add_executable(beman.inplace_vector.test inplace_vector.test.cpp)

target_link_libraries(beman.inplace_vector.test PRIVATE beman.inplace_vector)
Expand All @@ -20,6 +20,17 @@ add_test(
COMMAND beman.inplace_vector.ref-test
)

# 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
)

# GoogleTest based tests
include(GoogleTest)

Expand All @@ -43,7 +54,7 @@ add_gtest(erasure)
add_gtest(modifiers)
add_gtest(freestanding)

# only add noexception tests if NO_EXCEPTIONS option is set and compiler supports -fno-exceptions
# Only add noexception tests if NO_EXCEPTIONS option is set and compiler supports -fno-exceptions
if(
BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS
AND (
Expand All @@ -57,14 +68,3 @@ if(
PRIVATE -fno-exceptions
)
endif()

# 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
)
7 changes: 4 additions & 3 deletions tests/beman/inplace_vector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You can checkout `inplace_vector`'s [current state](https://eel.is/c++draft/inpl
#### 6.1 Overview

> An inplace_vector is a contiguous container. Its capacity is fixed and its
elements are stored within the inplace_vector object itself.
> elements are stored within the inplace_vector object itself.

This is not testable.

Expand All @@ -26,7 +26,7 @@ This is not testable.
> An inplace_vector meets all of the requirements of a container ([container.reqmts]),
> of a reversible container ([container.rev.reqmts]), of a contiguous container,
> and of a sequence container, including most of the optional sequence
container requirements ([sequence.reqmts]). The exceptions are the push_front,
> container requirements ([sequence.reqmts]). The exceptions are the push_front,
> prepend_range, pop_front, and emplace_front member functions,
> which are not provided.
> Descriptions are provided here only for operations on inplace_vector that
Expand All @@ -50,7 +50,7 @@ Not tested for now.
> then no `inplace_vector<T, N>` member functions are usable in
> constant expressions.

See [constexpr.test.cpp](constexpr.test.cpp),
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.
Expand All @@ -67,6 +67,7 @@ These are tested with individual functions.
#### 6.6 Triviality

Let IV denote a specialization of `inplace_vector<T, N>`.

> If N is zero, then IV is trivially copyable and empty,
> and std​::​is_trivially_default_constructible_v<IV> is true.
> (Sub-clauses omitted)
Expand Down
63 changes: 52 additions & 11 deletions tests/beman/inplace_vector/compare.test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>

#include <beman/inplace_vector/config.hpp>

#include <cmath>
#include <compare>

Expand All @@ -17,21 +18,23 @@ template <class T>
concept lessthan_comparable =
beman::inplace_vector::details::lessthan_comparable<T>;

template <typename T> struct vec_list {
T empty;
template <typename T, typename U = T> struct vec_list {
U empty;
T base; // base
T copy; // identical to base
T greater; // greater number of elements
T lesser; // lesser number of elements
T bigger; // bigger value of the elements
T smaller; // smaller value of the elements
T greater_smaller; // greater number of elements but smaller values
T lesser_bigger; // lesser number of elements but bigger values
U copy; // identical to base
U greater; // greater number of elements
U lesser; // lesser number of elements
U bigger; // bigger value of the elements
U smaller; // smaller value of the elements
U greater_smaller; // greater number of elements but smaller values
U lesser_bigger; // lesser number of elements but bigger values
};

template <typename T> static void runtests(vec_list<T> &list) {
template <typename T, typename U = T>
static void runtests(vec_list<T, U> &list) {

static_assert(std::three_way_comparable<T> || lessthan_comparable<T>);
static_assert(std::three_way_comparable<U> || lessthan_comparable<U>);

// if T::value_type is threewaycomparable with ordering X then T must also
// be comparable with ordering X
Expand Down Expand Up @@ -326,3 +329,41 @@ TEST(Compare, threeway_uncomparable) {
static_assert(!std::three_way_comparable<inplace_vector<uncomparable3, 4>>);
static_assert(!has_threeway<inplace_vector<uncomparable3, 4>>);
}

// In accordance with P3698R0, we compare vectors with identical elements but
// different capacities
#if BEMAN_INPLACE_VECTOR_CROSS_CAPACITY_COMPARISON()

TEST(Compare, threeway_cross_capacity) {
vec_list<inplace_vector<int, 4>, inplace_vector<int, 5>> list{
.empty{},
.base{1, 2, 3},
.copy{1, 2, 3},
.greater{4, 5, 6},
.lesser{0, 0, 0},
.bigger{1, 2, 3, 0},
.smaller{1, 2},
.greater_smaller{2, 2},
.lesser_bigger{0, 2, 3, 4},
};

runtests(list);
}

TEST(Compare, threeway_cross_capacity_full) {
vec_list<inplace_vector<int, 3>, inplace_vector<int, 4>> list{
.empty{},
.base{1, 2, 3},
.copy{1, 2, 3},
.greater{4, 5, 6},
.lesser{0, 0, 0},
.bigger{1, 2, 3, 0},
.smaller{1, 2},
.greater_smaller{2, 2},
.lesser_bigger{0, 2, 3, 4},
};

runtests(list);
}

#endif
1 change: 0 additions & 1 deletion tests/beman/inplace_vector/constexpr.test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/inplace_vector/inplace_vector.hpp>

#include <array>
Expand Down
3 changes: 2 additions & 1 deletion tests/beman/inplace_vector/constructors.test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>

#include <algorithm>
#include <gtest/gtest.h>
#include <numeric>

#include "gtest_setup.hpp"
Expand Down
4 changes: 2 additions & 2 deletions tests/beman/inplace_vector/container_requirements.test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>

#include "gtest/gtest.h"
#include <algorithm>
#include <array>
#include <gtest/gtest.h>
#include <new>

#include "gtest_setup.hpp"
Expand Down
3 changes: 2 additions & 1 deletion tests/beman/inplace_vector/erasure.test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>

#include <algorithm>
#include <gtest/gtest.h>

#include "gtest_setup.hpp"

Expand Down
4 changes: 2 additions & 2 deletions tests/beman/inplace_vector/freestanding.test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <array>
#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>

#include <array>

// constexpr void assign(InputIterator first, InputIterator last);
template <typename T>
concept has_assign_iterator = requires(T t, T::iterator it) {
Expand Down
7 changes: 3 additions & 4 deletions tests/beman/inplace_vector/gtest_setup.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>
#include <type_traits>

#include "beman/inplace_vector/inplace_vector.hpp"
#include <type_traits>

// We run the tests on various element types with the help of GoogleTest's
// typed tests. Which types shall we use?
Expand Down Expand Up @@ -287,7 +286,7 @@ struct NonTrivial {
}
friend constexpr bool operator==(NonTrivial x, NonTrivial y) = default;
};
std::size_t NonTrivial::num_objects;
inline std::size_t NonTrivial::num_objects;

template<typename T, typename = void>
struct counts_objects : std::false_type {};
Expand Down
1 change: 1 addition & 0 deletions tests/beman/inplace_vector/inplace_vector.test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <beman/inplace_vector/inplace_vector.hpp>

#include <cassert>

using namespace beman::inplace_vector;
Expand Down
3 changes: 2 additions & 1 deletion tests/beman/inplace_vector/modifiers.test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <beman/inplace_vector/inplace_vector.hpp>
#include <gtest/gtest.h>

#include <numeric>

#include "gtest_setup.hpp"
#include <gtest/gtest.h>

namespace {
// 23.3.14.5 Modifiers [inplace.vector.modifiers]
Expand Down
3 changes: 3 additions & 0 deletions tests/beman/inplace_vector/noexceptions.test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// #include <beman/inplace_vector/inplace_vector.hpp> 'BEMAN_IV_THROW_OR_ABORT'
// macro redfined
#include <gtest/gtest.h>

#include <array>

Expand Down
1 change: 0 additions & 1 deletion tests/beman/inplace_vector/ref_impl.test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#pragma GCC diagnostic ignored "-Wsign-compare"

/// \file
Expand Down
Loading