New components
set<Ts...>
,
The data structure of set
is essentially an inverse tree via inheritance, where the root is at the bottom and inherits from all of the children. A membership check then relies on std::is_base_of
to check if a child is a base of the root. i.e. exists in the set.
in<Set, T>
Adds a new specialization for in
: in<set<Set...>, T>
.
insert_back<Set, T>
The behavior of insert_back
is such that T
is inserted to Set
iff T
does not already exist in Set
.
unique<List>
Performs foldl
over List
performing insert_back
starting from set<>
to build up a unique set of types. We then convert it back to a list
using as_list
.
Performance
I ran tests for the worst case scenario for unique
which is when the list is already unique.
The generated program looks like this:
#include <type_traits>
#include "meta.hpp"
class T0 {};
class T1 {};
/* ... */
class Tn {};
static_assert(std::is_same<unique<list<T0, T1, ... Tn>>, list<T0, T1, ... Tn>>::value, "");
int main() {}
The following are numbers that I observed from my Macbook Retina Pro, using clang-3.5
.
Before
| # of types | seconds |
| --- | --- |
| 100 | 0.24 |
| 200 | 1.32 |
| 300 | 4.14 |
| 400 | 9.39 |
| 500 | 19.59 |
| 600 | ... |
After
| # of types | seconds |
| --- | --- |
| 100 | 0.07 |
| 200 | 0.17 |
| 300 | 0.34 |
| 400 | 0.56 |
| 500 | 0.85 |
| 600 | 1.24 |
| 700 | 1.65 |
| 800 | 2.24 |
| 900 | 2.81 |
| 1000 | 3.47 |
| 1500 | 8.3 |
| 2000 | 17.15 |
I was hoping that std::is_base_of
is performed as a constant time look-up in the compiler implementation but maybe it's not (I haven't looked), since I still observe quadratic growth with my implementation. But at least it seems to be a much lower curve.