Philipp Möller
using std::disclaimer;
Continuously raise the level of abstraction over input parameters.
Group those abstractions into Concepts.
Use concept refinement and hierarchies of concepts to expose implementation differences.
A concept is a set of requirements consisting of valid expressions, associated types, invariants, and complexity guarantees.
David Abrahams, Jeremy Siek
concept Stack<typename X> {
typename value_type;
void Stack::push(value_type);
void Stack::pop();
value_type Stack::top();
bool Stack::empty();
};
concept SinglePassRange<typename X> {
typedef iterator_type::type iterator;
where SinglePassIterator<iterator>;
iterator begin(X&); // notice free functions
iterator end(X&);
};
namespace mine {
struct my_vector {
int x[20];
};
int* begin(my_vector& x) { return x; }
int* begin(my_vector& x) { return x + 20; }
template<>
struct iterator_type {
typedef int* type;
};
}
A study of graph algorithms will produce Graph concepts that describe the behavior of graphs, whereas a study of linear algebra algorithms will produce Matrix and Vector concepts.Similar algorithms don not necessarily use similar predicates: where to lift your algorithms to?
Not all algorithms require full Halfedge Data Structures. Provide views on types:
Abstract optional features of Halfedge Data Structures into properties.
Algorithms require properties. Mutable algorithms can introspect for available properties and handle them.
template<typename... Options>
class Surface_mesh;
struct Vertex_properties {
Simple_cartesian<double>::Point_3 point;
};
Surface_mesh< Vertex_properties<Vertex_properties>
, Dynamic_properties<std::true_type>>
polyhedron;
for(auto& v : vertices(polyhedron)) {
// ...
}
BOOST_PARAMETER_FUNCTION(
(void),
join_vertex,
tag,
(required (graph, *) )
(required (edge, *) )
(optional
(next_map, *, boost::get(boost::edge_next, graph))
(prev_map, *, boost::get(boost::edge_prev, graph))
)
)
{ my_join_vertex_impl(graph, edge, next_map, prev_map); }
join_vertex(my_graph);