Skip to content

Commit 9d8387e

Browse files
Reduce recursion depth of fatal::filter
Summary: It's quite easy to hit the template recursion depth limit when trying to filter long lists. This diff adds a specialization to filter in "strides" of length 16 to reduce the recursion depth by up to 16X. Reviewed By: yfeldblum Differential Revision: D78781365 fbshipit-source-id: 36d2529a82f06d1693654896949f0e2545040a92
1 parent 817f9ef commit 9d8387e

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

fatal/type/impl/sort.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,45 @@ struct f<Predicate, Variadic<Result...>, T, Args...>:
127127
>
128128
{};
129129

130+
131+
template <
132+
typename Predicate,
133+
template <typename...> class Variadic,
134+
typename... Result,
135+
typename T0,
136+
typename T1,
137+
typename T2,
138+
typename T3,
139+
typename T4,
140+
typename T5,
141+
typename T6,
142+
typename T7,
143+
typename T8,
144+
typename T9,
145+
typename T10,
146+
typename T11,
147+
typename T12,
148+
typename T13,
149+
typename T14,
150+
typename T15,
151+
typename T16,
152+
typename... Args
153+
>
154+
struct f<
155+
Predicate, Variadic<Result...>,
156+
T0, T1, T2, T3, T4, T5, T6, T7, T8,
157+
T9, T10, T11, T12, T13, T14, T15, T16,
158+
Args...>:
159+
f<
160+
Predicate,
161+
typename f<
162+
Predicate, Variadic<Result...>,
163+
T0, T1, T2, T3, T4, T5, T6, T7,
164+
T8, T9, T10, T11, T12, T13, T14, T15>::type,
165+
T16, Args...
166+
>
167+
{};
168+
130169
template <typename...> struct F;
131170

132171
// TODO: OPTIMIZE

fatal/type/test/filter_test.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <fatal/type/list.h>
2+
#include <fatal/type/push.h>
3+
#include <fatal/type/sort.h>
4+
5+
#include <fatal/test/driver.h>
6+
7+
8+
namespace fatal {
9+
10+
template <int x> struct T{
11+
static constexpr int value = x;
12+
};
13+
14+
using L8 = list<T<1>, T<2>, T<3>, T<4>, T<5>, T<6>, T<7>, T<8>>;
15+
using L15 = cat<L8, list<T<9>, T<10>, T<11>, T<12>, T<13>, T<14>, T<15>>>;
16+
using L16 = push<L15>::back<T<16>>;
17+
using L17 = push<L16>::back<T<17>>;
18+
19+
using L32 = cat<L16, L16>;
20+
using L64 = cat<L32, L32>;
21+
using L128 = cat<L64, L64>;
22+
using L256 = cat<L128, L128>;
23+
using L512 = cat<L256, L256>;
24+
using L1024 = cat<L512, L512>;
25+
26+
27+
template <typename T>
28+
struct is_even{
29+
static constexpr bool value = T::value % 2 == 0;
30+
};
31+
32+
FATAL_TEST(filter, len1024){
33+
FATAL_EXPECT_EQ(size<L1024>::value, 1024);
34+
FATAL_EXPECT_EQ((size<filter<L1024, applier<is_even>>>::value), 512);
35+
}
36+
37+
FATAL_TEST(filter, len15){
38+
using expected = list<T<2>, T<4>, T<6>, T<8>, T<10>, T<12>, T<14>>;
39+
FATAL_EXPECT_SAME<filter<L15, applier<is_even>>, expected>();
40+
}
41+
42+
FATAL_TEST(filter, len16){
43+
using expected = list<T<2>, T<4>, T<6>, T<8>, T<10>, T<12>, T<14>, T<16>>;
44+
FATAL_EXPECT_SAME<filter<L16, applier<is_even>>, expected>();
45+
}
46+
47+
FATAL_TEST(filter, len17){
48+
using expected = list<T<2>, T<4>, T<6>, T<8>, T<10>, T<12>, T<14>, T<16>>;
49+
FATAL_EXPECT_SAME<filter<L17, applier<is_even>>, expected>();
50+
}
51+
52+
}

0 commit comments

Comments
 (0)