Skip to content

Commit

Permalink
Add verification of proper usage of `select_on_container_copy_constru…
Browse files Browse the repository at this point in the history
…ction` to unit tests
  • Loading branch information
gharveymn committed Nov 30, 2024
1 parent f391490 commit 9381079
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 1 deletion.
99 changes: 98 additions & 1 deletion source/test/test_allocators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ namespace gch
template <typename U>
constexpr GCH_IMPLICIT_CONVERSION
verifying_allocator (const verifying_allocator<U, PartialTraits>& other) noexcept
: base (other)
: base (other),
created_by_container_copy_construction (other.created_by_container_copy_construction)
{ }

GCH_NODISCARD
Expand Down Expand Up @@ -452,8 +453,44 @@ namespace gch
remove_object (p);
alloc_traits::destroy (*this, p);
}

verifying_allocator
select_on_container_copy_construction () const
{
verifying_allocator ret (*this);
ret.created_by_container_copy_construction = true;
return ret;
}

bool created_by_container_copy_construction = false;
};

template <typename A>
constexpr void
verify_created_by_container_copy_construction (const A& a)
{ }

template <typename T, typename Traits>
constexpr void
verify_created_by_container_copy_construction (const verifying_allocator<T, Traits>& a)
{
assert (a.created_by_container_copy_construction
&& "select_on_container_copy_construction unexpectedly invoked");
}

template <typename A>
constexpr void
verify_not_created_by_container_copy_construction (const A& a)
{ }

template <typename T, typename Traits>
constexpr void
verify_not_created_by_container_copy_construction (const verifying_allocator<T, Traits>& a)
{
assert (! a.created_by_container_copy_construction
&& "select_on_container_copy_construction unexpectedly not invoked");
}

template <typename T, typename Traits>
constexpr
bool
Expand Down Expand Up @@ -489,6 +526,12 @@ namespace gch
using propagate_on_container_move_assignment = std::false_type;
using propagate_on_container_copy_assignment = std::false_type;
using propagate_on_container_swap = std::false_type;

non_propagating_verifying_allocator
select_on_container_copy_construction () const
{
return non_propagating_verifying_allocator {};
}
};

template <typename T, typename Traits>
Expand Down Expand Up @@ -604,6 +647,60 @@ namespace gch
return ! (lhs == rhs);
}

template <typename Allocator>
class allocator_testing_traits
{
template <typename, typename = void>
struct has_created_by_container_copy_construction_field
: std::false_type
{ };

template <typename A>
struct has_created_by_container_copy_construction_field<A,
decltype((void) A::created_by_container_copy_construction, void ())>
: std::true_type
{ };

public:
template <typename A = Allocator,
typename std::enable_if<
has_created_by_container_copy_construction_field<A>::value
>::type * = nullptr>
constexpr void
verify_created_by_container_copy_construction (const A& a)
{
assert (a.created_by_container_copy_construction
&& "select_on_container_copy_construction unexpectedly not invoked");
}

template <typename A = Allocator,
typename std::enable_if<
! has_created_by_container_copy_construction_field<A>::value
>::type * = nullptr>
constexpr void
verify_created_by_container_copy_construction (const A&)
{ }

template <typename A = Allocator,
typename std::enable_if<
has_created_by_container_copy_construction_field<A>::value
>::type * = nullptr>
constexpr void
verify_not_created_by_container_copy_construction (const A& a)
{
assert (! a.created_by_container_copy_construction
&& "select_on_container_copy_construction unexpectedly not invoked");
}

template <typename A = Allocator,
typename std::enable_if<
! has_created_by_container_copy_construction_field<A>::value
>::type * = nullptr>
constexpr void
verify_not_created_by_container_copy_construction (const A&)
{ }
};

}

}
Expand Down
4 changes: 4 additions & 0 deletions source/test/unit/member/assign/test-copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ struct tester

n.assign (m);
CHECK (n == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (n.get_allocator ());
}
{
// vector_type<N> (ni) -> vector_type<M> (mi)
Expand All @@ -222,6 +223,7 @@ struct tester

m.assign (n);
CHECK (m == n_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (m.get_allocator ());
}
{
// vector_type<M> (ni) -> vector_type<N> (mi)
Expand All @@ -233,6 +235,7 @@ struct tester

n.assign (m);
CHECK (n == n_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (n.get_allocator ());
}
{
// vector_type<N> (mi) -> vector_type<M> (ni)
Expand All @@ -244,6 +247,7 @@ struct tester

m.assign (n);
CHECK (m == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (m.get_allocator ());
}
}

Expand Down
4 changes: 4 additions & 0 deletions source/test/unit/member/assign/test-move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ struct tester

n.assign (std::move (m));
CHECK (n == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (n.get_allocator ());
}
{
// vector_type<N> (ni) -> vector_type<M> (mi)
Expand All @@ -329,6 +330,7 @@ struct tester

m.assign (std::move (n));
CHECK (m == n_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (m.get_allocator ());
}
{
// vector_type<M> (ni) -> vector_type<N> (mi)
Expand All @@ -340,6 +342,7 @@ struct tester

n.assign (std::move (m));
CHECK (n == n_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (n.get_allocator ());
}
{
// vector_type<N> (mi) -> vector_type<M> (ni)
Expand All @@ -351,6 +354,7 @@ struct tester

m.assign (std::move (n));
CHECK (m == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (m.get_allocator ());
}
}

Expand Down
2 changes: 2 additions & 0 deletions source/test/unit/member/constructor/test-copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@ struct tester

vector_type<N> v (m);
CHECK (v == m_cmp);
gch::test_types::verify_created_by_container_copy_construction (v.get_allocator ());
}
{
vector_type<M> m (mi.begin (), mi.end (), m_alloc);
mi (m);

vector_type<N> v (m, m_alloc);
CHECK (v == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (v.get_allocator ());
}
}

Expand Down
2 changes: 2 additions & 0 deletions source/test/unit/member/constructor/test-move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,15 @@ struct tester

vector_type<N> v (std::move (m));
CHECK (v == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (v.get_allocator ());
}
{
vector_type<M> m (mi.begin (), mi.end (), m_alloc);
mi (m);

vector_type<N> v (std::move (m), m_init_alloc);
CHECK (v == m_cmp);
gch::test_types::verify_not_created_by_container_copy_construction (v.get_allocator ());
}
}

Expand Down

0 comments on commit 9381079

Please sign in to comment.