Skip to content

Commit 25b6aa1

Browse files
committed
Constain bounding_aabb_of with static sizing concept
1 parent a163dfa commit 25b6aa1

File tree

9 files changed

+75
-20
lines changed

9 files changed

+75
-20
lines changed

liboscar/Concepts/AssociativeContainerKey.h renamed to liboscar/Concepts/AssociativeContainerKeyFor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace osc
1010
// Satisfied if `Key` is a valid key for the given associative
1111
// container `Container`.
1212
template<typename Key, typename Container>
13-
concept AssociativeContainerKey = requires(Container& c, Key key) {
13+
concept AssociativeContainerKeyFor = requires(Container& c, Key key) {
1414
requires AssociativeContainer<Container>;
1515
{ c.find(key) } -> std::same_as<std::ranges::iterator_t<Container>>;
1616
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include <liboscar/Concepts/RangeWithSizeGreaterThan.h>
4+
5+
#include <ranges>
6+
7+
namespace osc
8+
{
9+
// Satisfied if `T` is a `std::ranges::input_range<T>` AND has a size that's
10+
// known at compile-time to be non-zero.
11+
template<typename T, size_t N>
12+
concept InputRangeWithSizeGreaterThan = std::ranges::input_range<T> and RangeWithSizeGreaterThan<T, N>;
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "InputRangeWithSizeGreaterThan.h"
2+
3+
#include <gtest/gtest.h>
4+
5+
#include <liboscar/Maths/Triangle.h>
6+
#include <liboscar/Maths/Vector3.h>
7+
8+
#include <array>
9+
#include <span>
10+
11+
using namespace osc;
12+
13+
TEST(InputRangeWithSizeGreaterThan, returns_false_for_dynamically_sized_std_span)
14+
{
15+
static_assert(InputRangeWithSizeGreaterThan<Vector3, 2>);
16+
static_assert(InputRangeWithSizeGreaterThan<Triangle, 2>);
17+
static_assert(InputRangeWithSizeGreaterThan<const Triangle&, 2>);
18+
static_assert(not InputRangeWithSizeGreaterThan<Triangle, 3>);
19+
static_assert(InputRangeWithSizeGreaterThan<std::span<int, 5>, 4>);
20+
static_assert(InputRangeWithSizeGreaterThan<std::array<int, 5>, 4>);
21+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
#include <concepts>
4+
#include <cstddef>
5+
#include <ranges>
6+
#include <tuple>
7+
8+
namespace osc
9+
{
10+
namespace detail
11+
{
12+
template<typename T> concept HasTupleSize = requires { std::tuple_size<std::remove_cvref_t<T>>{}; };
13+
template<typename T> concept HasExtent = requires { { std::remove_cvref_t<T>::extent } -> std::convertible_to<size_t>; };
14+
15+
template<typename T, typename = void>
16+
struct SizeHelper { static constexpr size_t size = std::dynamic_extent; };
17+
18+
template<HasTupleSize T>
19+
requires (not HasExtent<T>)
20+
struct SizeHelper<T> { static constexpr size_t size = std::tuple_size_v<std::remove_cvref_t<T>>; };
21+
22+
template<HasExtent T>
23+
struct SizeHelper<T> { static constexpr size_t size = std::remove_cvref_t<T>::extent; };
24+
}
25+
26+
// Satisfied if `T` has a compile-time-known size greater than `N`
27+
template<typename T, size_t N>
28+
concept RangeWithSizeGreaterThan = std::ranges::range<T> and (detail::SizeHelper<T>::size != std::dynamic_extent and detail::SizeHelper<T>::size > N);
29+
}

liboscar/Concepts/StaticallySizedNonEmptyInputRange.h

Lines changed: 0 additions & 11 deletions
This file was deleted.

liboscar/Maths/AABBFunctions.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include <liboscar/Concepts/StaticallySizedNonEmptyInputRange.h>
3+
#include <liboscar/Concepts/InputRangeWithSizeGreaterThan.h>
44
#include <liboscar/Maths/AABB.h>
55
#include <liboscar/Maths/CommonFunctions.h>
66
#include <liboscar/Maths/Matrix4x4.h>
@@ -136,7 +136,7 @@ namespace osc
136136
}
137137

138138
// returns an `AABB` that tightly bounds the `Vector3`s projected from `r` (specialized for compile-time-non-empty ranges)
139-
template<StaticallySizedNonEmptyInputRange R, class Proj = std::identity>
139+
template<InputRangeWithSizeGreaterThan<0> R, class Proj = std::identity>
140140
requires std::convertible_to<typename std::projected<std::ranges::iterator_t<R>, Proj>::value_type, const Vector3&>
141141
constexpr AABB bounding_aabb_of(R&& r, Proj proj = {})
142142
{

liboscar/Maths/Triangle.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ namespace osc
1717
using const_pointer = const value_type*;
1818
using iterator = value_type*;
1919
using const_iterator = const value_type*;
20+
static constexpr size_t extent = 3;
2021

21-
constexpr size_type size() const { return 3; }
22+
constexpr size_type size() const { return extent; }
2223
constexpr pointer data() { return &p0; }
2324
constexpr const_pointer data() const { return &p0; }
2425
constexpr iterator begin() { return data(); }

liboscar/Utils/Algorithms.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
#include <liboscar/Concepts/AssociativeContainer.h>
4-
#include <liboscar/Concepts/AssociativeContainerKey.h>
4+
#include <liboscar/Concepts/AssociativeContainerKeyFor.h>
55

66
#include <algorithm>
77
#include <concepts>
@@ -89,7 +89,7 @@ namespace osc
8989
}
9090

9191
// returns a copy of the element with key equivalent to `key`, or `std::nullopt` if no such element exists in `container`
92-
template<AssociativeContainer Lookup, AssociativeContainerKey<Lookup> Key>
92+
template<AssociativeContainer Lookup, AssociativeContainerKeyFor<Lookup> Key>
9393
std::optional<typename Lookup::mapped_type> lookup_or_nullopt(const Lookup& lookup, const Key& key)
9494
{
9595
if (const auto it = lookup.find(key); it != lookup.end()) {
@@ -112,7 +112,7 @@ namespace osc
112112
}
113113

114114
// returns a pointer to the element with key equivalent to `key`, or `nullptr` if no such element exists in `container`
115-
template<AssociativeContainer T, AssociativeContainerKey<T> Key>
115+
template<AssociativeContainer T, AssociativeContainerKeyFor<T> Key>
116116
auto* lookup_or_nullptr(const T& container, const Key& key)
117117
{
118118
using return_type = decltype(std::addressof(std::ranges::begin(container)->second));
@@ -124,7 +124,7 @@ namespace osc
124124
}
125125

126126
// returns a mutable pointer to the element with key equivalent to `key`, or `nullptr` if no such element exists in `container`
127-
template<AssociativeContainer T, AssociativeContainerKey<T> Key>
127+
template<AssociativeContainer T, AssociativeContainerKeyFor<T> Key>
128128
auto* lookup_or_nullptr(T& container, const Key& key)
129129
{
130130
using return_type = decltype(std::addressof(std::ranges::begin(container)->second));

liboscar/oscar.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
// ready for production, each translation unit should only `#include` it uses.
77

88
#include <liboscar/Concepts/AssociativeContainer.h>
9-
#include <liboscar/Concepts/AssociativeContainerKey.h>
9+
#include <liboscar/Concepts/AssociativeContainerKeyFor.h>
1010
#include <liboscar/Concepts/BitCastable.h>
1111
#include <liboscar/Concepts/ConvertibleToAnyOf.h>
1212
#include <liboscar/Concepts/DereferencesTo.h>
13+
#include <liboscar/Concepts/InputRangeWithSizeGreaterThan.h>
1314
#include <liboscar/Concepts/NamedInputStream.h>
1415
#include <liboscar/Concepts/ObjectRepresentationByte.h>
16+
#include <liboscar/Concepts/RangeWithSizeGreaterThan.h>
1517
#include <liboscar/Concepts/SameAsAnyOf.h>
1618
#include <liboscar/DOM/Class.h>
1719
#include <liboscar/DOM/Node.h>

0 commit comments

Comments
 (0)