Monoid Concept
(monoid/concept.hpp)
- View this file on GitHub
- Last update: 2026-07-16 20:44:42+09:00
- Include:
#include "monoid/concept.hpp"
Overview
m1une::monoid::IsMonoid is the C++20 concept used by generic data structures
such as Segtree. It checks that a type exposes the interface needed by the
library: a value type, an identity element, and a binary operation.
The concept checks the shape of the interface. The mathematical laws are still the user’s responsibility:
-
opshould be associative. -
id()should be a left and right identity forop.
Concept Requirements
To satisfy m1une::monoid::IsMonoid, a type M must implement:
-
using value_type = T;The type stored by the monoid. -
static T id();Returns the identity element. -
static T op(const T& a, const T& b);Combines two values.
Built-in monoids also expose static constexpr bool commutative. Generic data
structures may use it to select a faster representation. This member is
deliberately optional and is not part of IsMonoid, so a contest-local monoid
may omit it. An omitted flag is treated conservatively by data structures that
inspect it.
Group
m1une::monoid::IsGroup extends IsMonoid with an inverse:
-
static T inv(const T& x);Returns the inverse ofxwith respect toop.
The concept checks only that inv exists. The type must satisfy the group
laws, but op does not need to be commutative.
m1une::monoid::IsCommutativeGroup extends IsGroup. It has the same
compile-time interface check because C++ concepts cannot prove commutativity;
types used through it must additionally guarantee that op(a, b) == op(b, a).
Example
#include "monoid/concept.hpp"
#include <algorithm>
struct MinMonoid {
using value_type = int;
static constexpr int id() { return 1e9; }
static constexpr int op(const int& a, const int& b) { return std::min(a, b); }
};
static_assert(m1une::monoid::IsMonoid<MinMonoid>);
Complexity
These concepts are compile-time interface checks and have no runtime cost.
Required by
Range Update Range Product
(acted_monoid/range_update_range_product.hpp)
Range Update Range Product
(acted_monoid/range_update_range_product.hpp)
Binary Trie with Monoid
(ds/binary_trie/binary_trie_monoid.hpp)
DSU with Monoid
(ds/dsu/dsu_monoid.hpp)
Persistent Potentialized DSU
(ds/dsu/persistent_potentialized_dsu.hpp)
Potentialized DSU
(ds/dsu/potentialized_dsu.hpp)
Rollback Potentialized DSU
(ds/dsu/rollback_potentialized_dsu.hpp)
Dynamic Monoid Array
(ds/dynamic_array/dynamic_monoid_array.hpp)
Persistent Dynamic Monoid Array
(ds/dynamic_array/persistent_dynamic_monoid_array.hpp)
Rollback Dynamic Monoid Array
(ds/dynamic_array/rollback_dynamic_monoid_array.hpp)
Dynamic Connectivity
(ds/dynamic_connectivity/all.hpp)
Online Dynamic Connectivity
(ds/dynamic_connectivity/online_dynamic_connectivity.hpp)
Link-Cut Tree
(ds/dynamic_tree/link_cut_tree.hpp)
Path Link-Cut Tree
(ds/dynamic_tree/path_link_cut_tree.hpp)
Disjoint Sparse Table
(ds/range_query/disjoint_sparse_table.hpp)
Range Sort Range Composite
(ds/range_query/range_sort_range_composite.hpp)
Range Sort Range Composite
(ds/range_query/range_sort_range_composite.hpp)
Sliding Window Aggregation
(ds/range_query/sliding_window_aggregation.hpp)
Sliding Window Aggregation Deque
(ds/range_query/sliding_window_aggregation_deque.hpp)
Sparse Table
(ds/range_query/sparse_table.hpp)
Square-Root Decomposition
(ds/range_query/sqrt_decomposition.hpp)
Sqrt Tree
(ds/range_query/sqrt_tree.hpp)
Dual Segment Tree
(ds/segtree/dual_segtree.hpp)
Dual Segtree 2D
(ds/segtree/dual_segtree_2d.hpp)
Dynamic Dual Segment Tree
(ds/segtree/dynamic_dual_segtree.hpp)
Dynamic Segment Tree
(ds/segtree/dynamic_segtree.hpp)
Persistent Dual Segment Tree
(ds/segtree/persistent_dual_segtree.hpp)
Persistent Dynamic Dual Segment Tree
(ds/segtree/persistent_dynamic_dual_segtree.hpp)
Persistent Dynamic Segment Tree
(ds/segtree/persistent_dynamic_segtree.hpp)
Persistent Segment Tree
(ds/segtree/persistent_segtree.hpp)
Rollback Dual Segment Tree
(ds/segtree/rollback_dual_segtree.hpp)
Rollback Dynamic Dual Segment Tree
(ds/segtree/rollback_dynamic_dual_segtree.hpp)
Rollback Dynamic Segment Tree
(ds/segtree/rollback_dynamic_segtree.hpp)
Rollback Segment Tree
(ds/segtree/rollback_segtree.hpp)
Segment Tree
(ds/segtree/segtree.hpp)
Segtree 2D
(ds/segtree/segtree_2d.hpp)
Graph All
(graph/all.hpp)
Graph All
(graph/all.hpp)
Tree All
(graph/tree/all.hpp)
Tree All
(graph/tree/all.hpp)
Tree Cumulative Sum
(graph/tree/cumulative_sum.hpp)
Range Contour Query on Tree
(graph/tree/range_contour_query.hpp)
Sparse Table LCA
(graph/tree/sparse_table_lca.hpp)
Tree
(graph/tree/tree.hpp)
Tree
(graph/tree/tree.hpp)
Virtual Tree
(graph/tree/virtual_tree.hpp)
Monoid Power
(monoid/power.hpp)
Verified with
verify/ds/binary_trie/binary_trie_monoid.test.cpp
verify/ds/dsu/dsu_monoid.test.cpp
verify/ds/dsu/persistent_potentialized_dsu.test.cpp
verify/ds/dsu/potentialized_dsu.test.cpp
verify/ds/dsu/rollback_potentialized_dsu.test.cpp
verify/ds/dsu/unionfind_with_potential_non_commutative_group.test.cpp
verify/ds/dynamic_array/dynamic_monoid_array.test.cpp
verify/ds/dynamic_array/persistent_dynamic_monoid_array.test.cpp
verify/ds/dynamic_connectivity/dynamic_connectivity.test.cpp
verify/ds/dynamic_tree/link_cut_tree.test.cpp
verify/ds/dynamic_tree/path_link_cut_tree.test.cpp
verify/ds/persistent_cow.test.cpp
verify/ds/persistent_cow.test.cpp
verify/ds/persistent_cow.test.cpp
verify/ds/persistent_release.test.cpp
verify/ds/persistent_release.test.cpp
verify/ds/range_query/disjoint_sparse_table.test.cpp
verify/ds/range_query/range_sort_range_composite.test.cpp
verify/ds/range_query/range_sort_range_composite.test.cpp
verify/ds/range_query/sliding_window_aggregation.test.cpp
verify/ds/range_query/sliding_window_aggregation_deque.test.cpp
verify/ds/range_query/sparse_table.test.cpp
verify/ds/range_query/sqrt_decomposition.test.cpp
verify/ds/range_query/sqrt_tree.test.cpp
verify/ds/rollback_counterparts.test.cpp
verify/ds/rollback_counterparts.test.cpp
verify/ds/rollback_counterparts.test.cpp
verify/ds/segtree/dual_segtree.test.cpp
verify/ds/segtree/dual_segtree_2d.test.cpp
verify/ds/segtree/dynamic_dual_segtree.test.cpp
verify/ds/segtree/dynamic_segtree.test.cpp
verify/ds/segtree/persistent_dual_segtree.test.cpp
verify/ds/segtree/persistent_dynamic_dual_segtree.test.cpp
verify/ds/segtree/persistent_dynamic_segtree.test.cpp
verify/ds/segtree/persistent_segtree.test.cpp
verify/ds/segtree/range_update_range_product.test.cpp
verify/ds/segtree/range_update_range_product.test.cpp
verify/ds/segtree/segtree.test.cpp
verify/ds/segtree/segtree_2d.test.cpp
verify/graph/cow_game.test.cpp
verify/graph/cow_game.test.cpp
verify/graph/graph_algorithms.test.cpp
verify/graph/graph_algorithms.test.cpp
verify/graph/library_checker_lowest_common_ancestor.test.cpp
verify/graph/range_edge_graph.test.cpp
verify/graph/range_edge_graph.test.cpp
verify/graph/tree/tree_algorithms.test.cpp
verify/graph/tree/tree_algorithms.test.cpp
verify/graph/tree/tree_cumulative_sum.test.cpp
verify/graph/tree/vertex_add_range_contour_sum_on_tree.test.cpp
verify/graph/tree/vertex_get_range_contour_add_on_tree.test.cpp
verify/monoid/commutative_flags.test.cpp
verify/monoid/commutative_flags.test.cpp
verify/monoid/commutative_flags.test.cpp
Code
#ifndef M1UNE_MONOID_CONCEPT_HPP
#define M1UNE_MONOID_CONCEPT_HPP 1
#include <concepts>
namespace m1une {
namespace monoid {
// Concept to check if a type satisfies the requirements of a Monoid.
// A Monoid must have a `value_type`, an identity element `id()`, and an associative binary operation `op()`.
template <typename M>
concept IsMonoid = requires(typename M::value_type a, typename M::value_type b) {
// 1. Must define `value_type`
typename M::value_type;
// 2. Must have a static method `id()` returning `value_type`
{ M::id() } -> std::same_as<typename M::value_type>;
// 3. Must have a static method `op(a, b)` returning `value_type`
{ M::op(a, b) } -> std::same_as<typename M::value_type>;
};
// Concept for groups. A type satisfying this concept must also obey the group
// laws; concepts can check the interface but not the algebraic properties.
template <typename M>
concept IsGroup = IsMonoid<M> && requires(typename M::value_type a) {
{ M::inv(a) } -> std::same_as<typename M::value_type>;
};
// Concept for commutative groups. Commutativity is a semantic requirement and
// cannot be checked by a C++ concept.
template <typename M>
concept IsCommutativeGroup = IsGroup<M>;
} // namespace monoid
} // namespace m1une
#endif // M1UNE_MONOID_CONCEPT_HPP#line 1 "monoid/concept.hpp"
#include <concepts>
namespace m1une {
namespace monoid {
// Concept to check if a type satisfies the requirements of a Monoid.
// A Monoid must have a `value_type`, an identity element `id()`, and an associative binary operation `op()`.
template <typename M>
concept IsMonoid = requires(typename M::value_type a, typename M::value_type b) {
// 1. Must define `value_type`
typename M::value_type;
// 2. Must have a static method `id()` returning `value_type`
{ M::id() } -> std::same_as<typename M::value_type>;
// 3. Must have a static method `op(a, b)` returning `value_type`
{ M::op(a, b) } -> std::same_as<typename M::value_type>;
};
// Concept for groups. A type satisfying this concept must also obey the group
// laws; concepts can check the interface but not the algebraic properties.
template <typename M>
concept IsGroup = IsMonoid<M> && requires(typename M::value_type a) {
{ M::inv(a) } -> std::same_as<typename M::value_type>;
};
// Concept for commutative groups. Commutativity is a semantic requirement and
// cannot be checked by a C++ concept.
template <typename M>
concept IsCommutativeGroup = IsGroup<M>;
} // namespace monoid
} // namespace m1une