Skip to content

Commit 49c8304

Browse files
committed
Add freestanding build support
1 parent a739778 commit 49c8304

File tree

3 files changed

+91
-60
lines changed

3 files changed

+91
-60
lines changed

include/beman/inplace_vector/inplace_vector.hpp

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,13 @@ Software.
271271
// Artifact from previous implementation, can be used as hints for optimizer
272272
#define IV_EXPECT(EXPR)
273273

274+
#if (!defined(__EXCEPTIONS) && !defined(_CPPUNWIND)) || \
275+
__STDC_HOSTED__ == 0 || BEMAN_IV_FREESTANDING_FORCE_TEST
276+
#define BEMAN_IV_FREESTANDING_DELETE(impl) = delete
277+
#else
278+
#define BEMAN_IV_FREESTANDING_DELETE(impl) impl
279+
#endif
280+
274281
// beman::from_range_t
275282
namespace beman {
276283
struct from_range_t {};
@@ -531,10 +538,11 @@ struct inplace_vector
531538
static constexpr size_type capacity() noexcept { return N; }
532539
// constexpr void resize(size_type sz);
533540
// constexpr void resize(size_type sz, const T& c);
534-
constexpr void reserve(size_type n) {
541+
constexpr void reserve(size_type n) BEMAN_IV_FREESTANDING_DELETE({
535542
if (n > N) [[unlikely]]
536543
throw std::bad_alloc();
537-
}
544+
});
545+
538546
constexpr void shrink_to_fit() {}
539547

540548
// element access
@@ -663,23 +671,23 @@ struct inplace_vector
663671
template <class... Args>
664672
constexpr T &emplace_back(Args &&...args)
665673
requires(std::constructible_from<T, Args...>)
666-
{
674+
BEMAN_IV_FREESTANDING_DELETE({
667675
if (!try_emplace_back(std::forward<Args>(args)...)) [[unlikely]]
668676
throw std::bad_alloc();
669677
return back();
670-
}
678+
});
671679
constexpr T &push_back(const T &x)
672680
requires(std::constructible_from<T, const T &>)
673-
{
681+
BEMAN_IV_FREESTANDING_DELETE({
674682
emplace_back(x);
675683
return back();
676-
}
684+
});
677685
constexpr T &push_back(T &&x)
678686
requires(std::constructible_from<T, T &&>)
679-
{
687+
BEMAN_IV_FREESTANDING_DELETE({
680688
emplace_back(std::forward<T &&>(x));
681689
return back();
682-
}
690+
});
683691

684692
constexpr T *try_push_back(const T &x)
685693
requires(std::constructible_from<T, const T &>)
@@ -706,7 +714,7 @@ struct inplace_vector
706714
template <details::inplace_vector::container_compatible_range<T> R>
707715
constexpr void append_range(R &&rg)
708716
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
709-
{
717+
BEMAN_IV_FREESTANDING_DELETE({
710718
if constexpr (std::ranges::sized_range<R>) {
711719
if (size() + std::ranges::size(rg) > capacity()) [[unlikely]]
712720
throw std::bad_alloc();
@@ -716,26 +724,26 @@ struct inplace_vector
716724
throw std::bad_alloc();
717725
emplace_back(std::forward<decltype(e)>(e));
718726
}
719-
}
727+
});
720728

721729
template <class... Args>
722730
constexpr iterator emplace(const_iterator position, Args &&...args)
723731
requires(std::constructible_from<T, Args...> && std::movable<T>)
724-
{
732+
BEMAN_IV_FREESTANDING_DELETE({
725733
assert_iterator_in_range(position);
726734
auto b = end();
727735
emplace_back(std::forward<Args>(args)...);
728736
auto pos = begin() + (position - begin());
729737
std::rotate(pos, b, end());
730738
return pos;
731-
}
739+
});
732740

733741
template <class InputIterator>
734742
constexpr iterator insert(const_iterator position, InputIterator first,
735743
InputIterator last)
736744
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
737745
std::movable<T>)
738-
{
746+
BEMAN_IV_FREESTANDING_DELETE({
739747
assert_iterator_in_range(position);
740748
if constexpr (std::random_access_iterator<InputIterator>) {
741749
if (size() + static_cast<size_type>(std::distance(first, last)) >
@@ -748,85 +756,73 @@ struct inplace_vector
748756
auto pos = begin() + (position - begin());
749757
std::rotate(pos, b, end());
750758
return pos;
751-
}
759+
});
752760

753761
template <details::inplace_vector::container_compatible_range<T> R>
754762
constexpr iterator insert_range(const_iterator position, R &&rg)
755763
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
756764
std::movable<T>)
757-
{
765+
BEMAN_IV_FREESTANDING_DELETE({
758766
return insert(position, std::begin(rg), std::end(rg));
759-
}
767+
});
760768

761769
constexpr iterator insert(const_iterator position,
762770
std::initializer_list<T> il)
763771
requires(std::constructible_from<
764772
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
765773
std::movable<T>)
766-
{
767-
return insert_range(position, il);
768-
}
774+
BEMAN_IV_FREESTANDING_DELETE({ return insert_range(position, il); });
769775

770776
constexpr iterator insert(const_iterator position, size_type n, const T &x)
771777
requires(std::constructible_from<T, const T &> && std::copyable<T>)
772-
{
778+
BEMAN_IV_FREESTANDING_DELETE({
773779
assert_iterator_in_range(position);
774780
auto b = end();
775781
for (size_type i = 0; i < n; ++i)
776782
emplace_back(x);
777783
auto pos = begin() + (position - begin());
778784
std::rotate(pos, b, end());
779785
return pos;
780-
}
786+
});
781787

782788
constexpr iterator insert(const_iterator position, const T &x)
783789
requires(std::constructible_from<T, const T &> && std::copyable<T>)
784-
{
785-
return insert(position, 1, x);
786-
}
790+
BEMAN_IV_FREESTANDING_DELETE({ return insert(position, 1, x); });
787791

788792
constexpr iterator insert(const_iterator position, T &&x)
789793
requires(std::constructible_from<T, T &&> && std::movable<T>)
790-
{
791-
return emplace(position, std::move(x));
792-
}
794+
BEMAN_IV_FREESTANDING_DELETE({ return emplace(position, std::move(x)); });
793795

794796
constexpr inplace_vector(std::initializer_list<T> il)
795797
requires(std::constructible_from<
796798
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
797799
std::movable<T>)
798-
{
799-
insert(begin(), il);
800-
}
800+
BEMAN_IV_FREESTANDING_DELETE({ insert(begin(), il); });
801801

802802
constexpr inplace_vector(size_type n, const T &value)
803803
requires(std::constructible_from<T, const T &> && std::copyable<T>)
804-
{
805-
insert(begin(), n, value);
806-
}
804+
BEMAN_IV_FREESTANDING_DELETE({ insert(begin(), n, value); });
807805

808806
constexpr explicit inplace_vector(size_type n)
809807
requires(std::constructible_from<T, T &&> && std::default_initializable<T>)
810-
{
808+
BEMAN_IV_FREESTANDING_DELETE({
811809
for (size_type i = 0; i < n; ++i)
812810
emplace_back(T{});
813-
}
811+
});
814812

815813
template <class InputIterator> // BUGBUG: why not std::ranges::input_iterator?
816814
constexpr inplace_vector(InputIterator first, InputIterator last)
817815
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
818816
std::movable<T>)
819-
{
820-
insert(begin(), first, last);
821-
}
817+
BEMAN_IV_FREESTANDING_DELETE({ insert(begin(), first, last); });
822818

823819
template <details::inplace_vector::container_compatible_range<T> R>
824820
constexpr inplace_vector(beman::from_range_t, R &&rg)
825821
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
826822
std::movable<T>)
827-
{
823+
BEMAN_IV_FREESTANDING_DELETE({
828824
insert_range(begin(), std::forward<R &&>(rg));
829-
}
825+
});
830826

831827
constexpr iterator erase(const_iterator first, const_iterator last)
832828
requires(std::movable<T>)
@@ -853,7 +849,7 @@ struct inplace_vector
853849

854850
constexpr void resize(size_type sz, const T &c)
855851
requires(std::constructible_from<T, const T &> && std::copyable<T>)
856-
{
852+
BEMAN_IV_FREESTANDING_DELETE({
857853
if (sz == size())
858854
return;
859855
else if (sz > N) [[unlikely]]
@@ -864,10 +860,10 @@ struct inplace_vector
864860
unsafe_destroy(begin() + sz, end());
865861
unsafe_set_size(sz);
866862
}
867-
}
863+
});
868864
constexpr void resize(size_type sz)
869865
requires(std::constructible_from<T, T &&> && std::default_initializable<T>)
870-
{
866+
BEMAN_IV_FREESTANDING_DELETE({
871867
if (sz == size())
872868
return;
873869
else if (sz > N) [[unlikely]]
@@ -879,18 +875,19 @@ struct inplace_vector
879875
unsafe_destroy(begin() + sz, end());
880876
unsafe_set_size(sz);
881877
}
882-
}
878+
});
883879

884-
constexpr reference at(size_type pos) {
880+
constexpr reference at(size_type pos) BEMAN_IV_FREESTANDING_DELETE({
885881
if (pos >= size()) [[unlikely]]
886882
throw std::out_of_range("inplace_vector::at");
887883
return details::inplace_vector::index(*this, pos);
888-
}
889-
constexpr const_reference at(size_type pos) const {
890-
if (pos >= size()) [[unlikely]]
891-
throw std::out_of_range("inplace_vector::at");
892-
return details::inplace_vector::index(*this, pos);
893-
}
884+
});
885+
constexpr const_reference at(size_type pos) const
886+
BEMAN_IV_FREESTANDING_DELETE({
887+
if (pos >= size()) [[unlikely]]
888+
throw std::out_of_range("inplace_vector::at");
889+
return details::inplace_vector::index(*this, pos);
890+
});
894891

895892
constexpr void pop_back() {
896893
IV_EXPECT(size() > 0 && "pop_back from empty inplace_vector!");
@@ -975,31 +972,29 @@ struct inplace_vector
975972
constexpr void assign(InputIterator first, InputIterator last)
976973
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
977974
std::movable<T>)
978-
{
975+
BEMAN_IV_FREESTANDING_DELETE({
979976
clear();
980977
insert(begin(), first, last);
981-
}
978+
});
982979
template <details::inplace_vector::container_compatible_range<T> R>
983980
constexpr void assign_range(R &&rg)
984981
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
985982
std::movable<T>)
986-
{
987-
assign(std::begin(rg), std::end(rg));
988-
}
983+
BEMAN_IV_FREESTANDING_DELETE({ assign(std::begin(rg), std::end(rg)); });
989984
constexpr void assign(size_type n, const T &u)
990985
requires(std::constructible_from<T, const T &> && std::movable<T>)
991-
{
986+
BEMAN_IV_FREESTANDING_DELETE({
992987
clear();
993988
insert(begin(), n, u);
994-
}
989+
});
995990
constexpr void assign(std::initializer_list<T> il)
996991
requires(std::constructible_from<
997992
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
998993
std::movable<T>)
999-
{
994+
BEMAN_IV_FREESTANDING_DELETE({
1000995
clear();
1001996
insert_range(begin(), il);
1002-
}
997+
});
1003998

1004999
constexpr friend int /*synth-three-way-result<T>*/
10051000
operator<=>(const inplace_vector & x, const inplace_vector & y) {
@@ -1044,3 +1039,4 @@ constexpr std::size_t erase_if(inplace_vector<T, N> &c, Predicate pred) {
10441039
} // namespace beman
10451040

10461041
#undef IV_EXPECT
1042+
#undef BEMAN_IV_FREESTANDING_DELETE

tests/beman/inplace_vector/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ add_gtest(triviality)
4040
add_gtest(constructors)
4141
add_gtest(size_n_data)
4242
add_gtest(erasure)
43+
add_gtest(freestanding)
44+
45+
set_source_files_properties(
46+
freestanding.test.cpp
47+
PROPERTIES COMPILE_FLAGS "-DBEMAN_IV_FREESTANDING_FORCE_TEST"
48+
)
4349

4450
# constexpr test
4551
add_executable(beman.inplace_vector.tests.constexpr constexpr.test.cpp)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <gtest/gtest.h>
2+
#include <type_traits>
3+
4+
#include "gtest_setup.hpp"
5+
6+
namespace {
7+
8+
template <typename Param> class Freestanding : public IVBasicTest<Param> {};
9+
TYPED_TEST_SUITE(Freestanding, IVAllTypes);
10+
11+
TYPED_TEST(Freestanding, alltypes) {
12+
13+
using IV = TestFixture::IV;
14+
using T = TestFixture::T;
15+
using size_type = IV::size_type;
16+
17+
IV vec;
18+
for (size_type i = 0; i < IV::capacity(); ++i) {
19+
EXPECT_NE(vec.try_push_back(T{}), nullptr);
20+
}
21+
EXPECT_EQ(vec.try_push_back(T{}), nullptr);
22+
23+
EXPECT_EQ(vec.size(), IV::capacity());
24+
25+
vec.clear();
26+
EXPECT_EQ(vec.size(), 0);
27+
28+
}
29+
} // namespace

0 commit comments

Comments
 (0)