Skip to content

Commit 5f039b5

Browse files
committed
docu traits iterator
1 parent 8acafa5 commit 5f039b5

2 files changed

Lines changed: 149 additions & 19 deletions

File tree

include/osp/concepts/graph_traits.hpp

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,28 @@ limitations under the License.
2020

2121
#include "iterator_concepts.hpp"
2222

23+
/**
24+
* @file graph_traits.hpp
25+
* @brief Type traits and concepts for graph structures in OneStopParallel.
26+
*
27+
* This file defines the core requirements for types used by graph implementations in the library,
28+
* specifically for computational DAGs. It provides mechanisms
29+
* to extract types for vertex indices, edge descriptors, and weights,
30+
* ensuring that graph implementations conform to the expected interfaces.
31+
*/
32+
2333
namespace osp {
2434

25-
#define DEFINE_TYPE_MEMBER_TEST(test_name, member_name) \
26-
template<typename T, typename = void> \
27-
struct test_name : std::false_type {}; \
28-
template<typename T> \
35+
/**
36+
* @brief Macro to define a trait that checks for the existence of a specific type member.
37+
*
38+
* Creates a struct `test_name<T>` inheriting from `std::true_type` if `T::member_name` exists,
39+
* otherwise inherits from `std::false_type`.
40+
*/
41+
#define DEFINE_TYPE_MEMBER_TEST(test_name, member_name) \
42+
template<typename T, typename = void> \
43+
struct test_name : std::false_type {}; \
44+
template<typename T> \
2945
struct test_name<T, std::void_t<typename T::member_name>> : std::true_type {};
3046

3147
DEFINE_TYPE_MEMBER_TEST(has_vertex_idx_tmember, vertex_idx)
@@ -36,17 +52,33 @@ DEFINE_TYPE_MEMBER_TEST(has_vertex_mem_weight_tmember, vertex_mem_weight_type)
3652
DEFINE_TYPE_MEMBER_TEST(has_vertex_type_tmember, vertex_type_type)
3753
DEFINE_TYPE_MEMBER_TEST(has_edge_comm_weight_tmember, edge_comm_weight_type)
3854

39-
// Every directed graph must have a vertex_idx type
55+
/**
56+
* @brief Core traits for any directed graph type.
57+
*
58+
* Requires that the graph type `T` defines a `vertex_idx` type member.
59+
*
60+
* @tparam T The graph type.
61+
*/
4062
template<typename T>
4163
struct directed_graph_traits {
4264
static_assert(has_vertex_idx_tmember<T>::value, "graph must have vertex_idx");
4365
using vertex_idx = typename T::vertex_idx;
4466
};
4567

46-
// Macro to extract the vertex_idx type from the graph
68+
/**
69+
* @brief Alias to easily access the vertex index type of a graph.
70+
*/
4771
template<typename T>
4872
using vertex_idx_t = typename directed_graph_traits<T>::vertex_idx;
4973

74+
/**
75+
* @brief A default edge descriptor for directed graphs.
76+
*
77+
* This struct is used when the graph type does not provide its own edge descriptor.
78+
* It simply holds the source and target vertex indices.
79+
*
80+
* @tparam Graph_t The graph type.
81+
*/
5082
template<typename Graph_t>
5183
struct directed_edge {
5284

@@ -65,6 +97,11 @@ struct directed_edge {
6597
directed_edge(vertex_idx_t<Graph_t> src, vertex_idx_t<Graph_t> tgt) : source(src), target(tgt) {}
6698
};
6799

100+
/**
101+
* @brief Helper struct to extract the edge descriptor type of a directed graph.
102+
*
103+
* If the graph defines `directed_edge_descriptor`, it is extracted; otherwise, `directed_edge` is used as a default implementation.
104+
*/
68105
template<typename T, bool has_edge>
69106
struct directed_graph_edge_desc_traits_helper {
70107
using directed_edge_descriptor = directed_edge<T>;
@@ -84,6 +121,16 @@ struct directed_graph_edge_desc_traits {
84121
template<typename T>
85122
using edge_desc_t = typename directed_graph_edge_desc_traits<T>::directed_edge_descriptor;
86123

124+
/**
125+
* @brief Traits for computational Directed Acyclic Graphs (DAGs).
126+
*
127+
* Computational DAGs extend basic graphs by adding requirements for weight types:
128+
* - `vertex_work_weight_type`: Represents computational cost of a task.
129+
* - `vertex_comm_weight_type`: Represents data size/communication cost.
130+
* - `vertex_mem_weight_type`: Represents memory usage of a task.
131+
*
132+
* @tparam T The computational DAG type.
133+
*/
87134
template<typename T>
88135
struct computational_dag_traits {
89136
static_assert(has_vertex_work_weight_tmember<T>::value, "cdag must have vertex work weight type");
@@ -104,6 +151,11 @@ using v_commw_t = typename computational_dag_traits<T>::vertex_comm_weight_type;
104151
template<typename T>
105152
using v_memw_t = typename computational_dag_traits<T>::vertex_mem_weight_type;
106153

154+
/**
155+
* @brief Traits to extract the vertex type of a computational DAG, if defined.
156+
*
157+
* If the DAG defines `vertex_type_type`, it is extracted; otherwise, `void` is used.
158+
*/
107159
template<typename T, typename = void>
108160
struct computational_dag_typed_vertices_traits {
109161
using vertex_type_type = void;
@@ -117,6 +169,11 @@ struct computational_dag_typed_vertices_traits<T, std::void_t<typename T::vertex
117169
template<typename T>
118170
using v_type_t = typename computational_dag_typed_vertices_traits<T>::vertex_type_type;
119171

172+
/**
173+
* @brief Traits to extract the edge communication weight type of a computational DAG, if defined.
174+
*
175+
* If the DAG defines `edge_comm_weight_type`, it is extracted; otherwise, `void` is used.
176+
*/
120177
template<typename T, typename = void>
121178
struct computational_dag_edge_desc_traits {
122179
using edge_comm_weight_type = void;
@@ -130,6 +187,14 @@ struct computational_dag_edge_desc_traits<T, std::void_t<typename T::edge_comm_w
130187
template<typename T>
131188
using e_commw_t = typename computational_dag_edge_desc_traits<T>::edge_comm_weight_type;
132189

190+
// -----------------------------------------------------------------------------
191+
// Property Traits
192+
// -----------------------------------------------------------------------------
193+
194+
/**
195+
* @brief Check if a graph guarantees vertices are stored/iterated in topological order.
196+
* It allows a graph implementation to notify algorithms that vertices are stored/iterated in topological order which can be used to optimize the algorithm.
197+
*/
133198
template<typename T, typename = void>
134199
struct has_vertices_in_top_order_trait : std::false_type {};
135200

@@ -140,6 +205,9 @@ struct has_vertices_in_top_order_trait<T, std::void_t<decltype(T::vertices_in_to
140205
template<typename T>
141206
inline constexpr bool has_vertices_in_top_order_v = has_vertices_in_top_order_trait<T>::value;
142207

208+
/**
209+
* @brief Check if a graph guarantees children of a vertex are stored/iterated in vertex index order.
210+
*/
143211
template<typename T, typename = void>
144212
struct has_children_in_vertex_order_trait : std::false_type {};
145213

@@ -150,6 +218,9 @@ struct has_children_in_vertex_order_trait<T, std::void_t<decltype(T::children_in
150218
template<typename T>
151219
inline constexpr bool has_children_in_vertex_order_v = has_children_in_vertex_order_trait<T>::value;
152220

221+
/**
222+
* @brief Check if a graph guarantees parents of a vertex are stored/iterated in vertex index order.
223+
*/
153224
template<typename T, typename = void>
154225
struct has_parents_in_vertex_order_trait : std::false_type {};
155226

@@ -162,6 +233,11 @@ inline constexpr bool has_parents_in_vertex_order_v = has_parents_in_vertex_orde
162233

163234
} // namespace osp
164235

236+
/**
237+
* @brief Specialization of std::hash for osp::directed_edge.
238+
*
239+
* This specialization provides a hash function for osp::directed_edge, which is used in hash-based containers like std::unordered_set and std::unordered_map.
240+
*/
165241
template<typename Graph_t>
166242
struct std::hash<osp::directed_edge<Graph_t>> {
167243
std::size_t operator()(const osp::directed_edge<Graph_t> &p) const noexcept {

include/osp/concepts/iterator_concepts.hpp

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,35 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
16-
@author Toni Boehnlein, Benjamin Lozes, Pal Andras Papp, Raphael S. Steiner
16+
@author Toni Boehnlein, Benjamin Lozes, Pal Andras Papp, Raphael S. Steiner
1717
*/
1818

19-
2019
#pragma once
2120

2221
#include <iterator>
2322
#include <type_traits>
2423

2524
namespace osp {
26-
27-
// Concept for const_iterator with forward iterator category
25+
/**
26+
* @file iterator_concepts.hpp
27+
* @brief C++17 compatible concept checks (type traits) for iterators and ranges.
28+
*
29+
* This file provides type traits that emulate C++20 concepts for iterators and ranges.
30+
* These are used to ensure type safety and correct usage of templates within the library
31+
* while maintaining compatibility with C++17.
32+
*/
33+
34+
/**
35+
* @brief Checks if a type is a forward iterator.
36+
*
37+
* This type trait checks if `T` satisfies the requirements of a forward iterator.
38+
* It verifies the existence of standard iterator typedefs and checks if the iterator category
39+
* is derived from `std::forward_iterator_tag`.
40+
*
41+
* @note Equivalent to C++20 `std::forward_iterator`.
42+
*
43+
* @tparam T The type to check.
44+
*/
2845
template<typename T, typename = void>
2946
struct is_forward_iterator : std::false_type {};
3047

@@ -41,14 +58,24 @@ struct is_forward_iterator<
4158
template<typename T>
4259
inline constexpr bool is_forward_iterator_v = is_forward_iterator<T>::value;
4360

44-
// Concept for ranges with const forward iterators supporting begin or cbegin
61+
/**
62+
* @brief Checks if a type is a range of forward iterators with a specific value type.
63+
*
64+
* This type trait checks if `T` is a range (provides `begin()` and `end()`) whose iterator
65+
* satisfies `is_forward_iterator` and whose value type matches `ValueType`.
66+
*
67+
* @note Equivalent to C++20 `std::ranges::forward_range` combined with a value type check.
68+
*
69+
* @tparam T The range type to check.
70+
* @tparam ValueType The expected value type of the range.
71+
*/
4572
template<typename T, typename ValueType, typename = void>
4673
struct is_forward_range_of : std::false_type {};
4774

4875
template<typename T, typename ValueType>
4976
struct is_forward_range_of<
5077
T, ValueType,
51-
std::void_t<decltype(std::begin(std::declval<T>())),
78+
std::void_t<decltype(std::begin(std::declval<T>())),
5279
decltype(std::end(std::declval<T>()))>>
5380
: std::conjunction<
5481
is_forward_iterator<decltype(std::begin(std::declval<T>()))>,
@@ -57,7 +84,17 @@ struct is_forward_range_of<
5784
template<typename T, typename ValueType>
5885
inline constexpr bool is_forward_range_of_v = is_forward_range_of<T, ValueType>::value;
5986

60-
// Concept for containers
87+
/**
88+
* @brief Checks if a type is a container (sized forward range).
89+
*
90+
* This type trait checks if `T` satisfies `is_forward_range_of` and additionally provides
91+
* a `size()` member function.
92+
*
93+
* @note Equivalent to C++20 `std::ranges::sized_range` combined with `std::ranges::forward_range`.
94+
*
95+
* @tparam T The container type to check.
96+
* @tparam ValueType The expected value type of the container.
97+
*/
6198
template<typename T, typename ValueType, typename = void>
6299
struct is_container_of : std::false_type {};
63100

@@ -71,9 +108,17 @@ struct is_container_of<
71108
template<typename T, typename ValueType>
72109
inline constexpr bool is_container_of_v = is_container_of<T, ValueType>::value;
73110

74-
75-
76-
// Concept for const_iterator with forward iterator category
111+
/**
112+
* @brief Checks if a type is an input iterator.
113+
*
114+
* This type trait checks if `T` satisfies the requirements of an input iterator.
115+
* It verifies the existence of standard iterator typedefs and checks if the iterator category
116+
* is derived from `std::input_iterator_tag`.
117+
*
118+
* @note Equivalent to C++20 `std::input_iterator`.
119+
*
120+
* @tparam T The type to check.
121+
*/
77122
template<typename T, typename = void>
78123
struct is_input_iterator : std::false_type {};
79124

@@ -90,14 +135,24 @@ struct is_input_iterator<
90135
template<typename T>
91136
inline constexpr bool is_input_iterator_v = is_input_iterator<T>::value;
92137

93-
// Concept for ranges with const input iterators supporting begin or cbegin
138+
/**
139+
* @brief Checks if a type is a range of input iterators with a specific value type.
140+
*
141+
* This type trait checks if `T` is a range (provides `begin()` and `end()`) whose iterator
142+
* satisfies `is_input_iterator` and whose value type matches `ValueType`.
143+
*
144+
* @note Equivalent to C++20 `std::ranges::input_range` combined with a value type check.
145+
*
146+
* @tparam T The range type to check.
147+
* @tparam ValueType The expected value type of the range.
148+
*/
94149
template<typename T, typename ValueType, typename = void>
95150
struct is_input_range_of : std::false_type {};
96151

97152
template<typename T, typename ValueType>
98153
struct is_input_range_of<
99154
T, ValueType,
100-
std::void_t<decltype(std::begin(std::declval<T>())),
155+
std::void_t<decltype(std::begin(std::declval<T>())),
101156
decltype(std::end(std::declval<T>()))>>
102157
: std::conjunction<
103158
is_input_iterator<decltype(std::begin(std::declval<T>()))>,
@@ -106,5 +161,4 @@ struct is_input_range_of<
106161
template<typename T, typename ValueType>
107162
inline constexpr bool is_input_range_of_v = is_input_range_of<T, ValueType>::value;
108163

109-
110164
} // namespace osp

0 commit comments

Comments
 (0)