Skip to content

Commit cbaf07b

Browse files
committed
Add inline documentation comparing fold expression vs binary tree approaches
Detailed comments explain: - Why fold expressions achieve O(1) template depth for sequence_merge - Comprehensive comparison of three approaches: recursive O(N), binary tree O(log N), fold expression O(1) - Trade-offs: C++17 requirement, ADL complexity, debugging difficulty - Clear recommendations for when to use each approach - How operator| enables fold expression pattern via ADL This documentation helps maintainers understand the performance vs complexity trade-offs between different sequence merging strategies.
1 parent 2d9c443 commit cbaf07b

1 file changed

Lines changed: 46 additions & 3 deletions

File tree

include/ck/utility/sequence.hpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,52 @@ template <index_t N>
199199
using make_index_sequence =
200200
typename __make_integer_seq<impl::__integer_sequence, index_t, N>::seq_type;
201201

202-
// merge sequence - O(1) template depth using fold expression
203-
// Binary merge operator for fold expression - enables O(1) depth via (S1 | S2 | S3 | ...)
204-
// Must be in ck namespace for ADL to find it when used with Sequence types
202+
// Sequence merge using fold expressions - O(1) template instantiation depth
203+
//
204+
// Strategy: Use C++17 fold expressions with custom operator| to achieve true O(1) depth
205+
//
206+
// Why fold expressions achieve O(1) depth:
207+
// - Fold expression: (Seq1{} | Seq2{} | Seq3{} | ...) expands in a single step
208+
// - Compiler generates flat operation: operator|(operator|(Seq1, Seq2), Seq3), ...
209+
// - Single instantiation of operator| handles all pairs → O(1) template nesting depth
210+
//
211+
// Comparison with alternative approaches:
212+
//
213+
// 1. Recursive template (old approach):
214+
// - Depth: O(N) - each merge level requires template instantiation
215+
// - Example: merge<A,B,C,D> → merge<merge<A,B>, merge<C,D>> → multiple levels
216+
//
217+
// 2. Binary tree reduction (alternative O(log N) approach):
218+
// - Depth: O(log N) - divides work in half each level
219+
// - Example: merge<A,B,C,D> → merge<AB, CD> → ABCD (2 levels for 4 sequences)
220+
// - Specializes small cases (1-4 sequences) for common scenarios
221+
//
222+
// 3. Fold expression (THIS approach):
223+
// - Depth: O(1) - single fold operation regardless of N
224+
// - Example: (A | B | C | D) → ABCD (1 level for any N)
225+
// - Requires C++17 and understanding of ADL for operator|
226+
//
227+
// Impact:
228+
// - Significantly reduces sequence_merge instantiation count vs recursive approach
229+
// - Maximum template nesting depth remains constant regardless of number of sequences
230+
// - Compilation time improvement proportional to instantiation reduction
231+
//
232+
// Trade-offs:
233+
// - Requires C++17 fold expressions
234+
// - Operator| must be found via ADL (Argument-Dependent Lookup) in ck namespace
235+
// - More abstract than explicit specializations (harder to debug)
236+
// - Uniform cost for all cases (no special-casing of common small N)
237+
//
238+
// Recommendation: Use fold expressions when:
239+
// - C++17 is available
240+
// - Maximum compilation performance is critical
241+
// - Code abstraction is acceptable
242+
//
243+
// Use binary tree (alternative approach) when:
244+
// - Need C++14 compatibility
245+
// - Want explicit control over small-case optimizations
246+
// - Debugging and code clarity are prioritized
247+
//
205248
template <index_t... As, index_t... Bs>
206249
constexpr Sequence<As..., Bs...> operator|(Sequence<As...>, Sequence<Bs...>)
207250
{

0 commit comments

Comments
 (0)