12#ifndef O2_FRAMEWORK_ASOAHELPERS_H_
13#define O2_FRAMEWORK_ASOAHELPERS_H_
17#include <arrow/table.h>
26template <std::
size_t V>
28 static const constexpr auto value = V;
31template <
class F, std::size_t... Is>
34 using expander =
int[];
38template <std::
size_t N,
typename F>
41 for_(
func, std::make_index_sequence<N>());
45template <
typename T,
unsigned N,
typename... REST>
50template <
typename T,
typename... REST>
52 using type = std::tuple<REST...>;
71 return a.bin >=
b.bin;
76template <
template <
typename... Cs>
typename BP,
typename T,
typename... Cs>
77std::vector<BinningIndex>
groupTable(
const T& table,
const BP<Cs...>& binningPolicy,
int minCatSize,
int outsider)
79 std::vector<BinningIndex> groupedIndices;
81 for (
auto rowIterator : table) {
82 auto values = binningPolicy.getBinningValues(rowIterator);
84 if (
val != outsider) {
85 groupedIndices.emplace_back(
val, *std::get<1>(rowIterator.getIndices()));
91 std::stable_sort(groupedIndices.begin(), groupedIndices.end());
95 auto catBegin = groupedIndices.begin();
96 while (catBegin != groupedIndices.end()) {
97 auto catEnd = std::upper_bound(catBegin, groupedIndices.end(), *catBegin,
sameCategory);
98 if (std::distance(catBegin, catEnd) < minCatSize) {
99 catEnd = groupedIndices.erase(catBegin, catEnd);
105 return groupedIndices;
109template <std::
size_t K>
112 std::vector<BinningIndex> firstCategories;
113 std::vector<BinningIndex> commonCategories;
114 std::unique_copy(groupedIndices[0].begin(), groupedIndices[0].
end(), std::back_inserter(firstCategories),
diffCategory);
116 for (
auto& cat : firstCategories) {
117 bool isCommon =
true;
118 for (
int i = 1;
i < K;
i++) {
119 if (!std::binary_search(groupedIndices[
i].begin(), groupedIndices[
i].
end(), cat,
sameCategory)) {
125 commonCategories.push_back(cat);
129 for (
int i = 0;
i < K;
i++) {
130 auto nonCatBegin = groupedIndices[
i].begin();
131 for (
auto& cat : commonCategories) {
132 auto nonCatEnd = std::lower_bound(nonCatBegin, groupedIndices[
i].
end(), cat,
sameCategory);
133 nonCatEnd = groupedIndices[
i].erase(nonCatBegin, nonCatEnd);
134 nonCatBegin = std::upper_bound(nonCatEnd, groupedIndices[
i].
end(), cat,
sameCategory);
139template <
typename...
Ts>
145 template <
typename... Tss>
150 if (((tables.size() == 0) || ...)) {
154 template <
typename... Tss>
160 std::apply([](
auto&&...
x) ->
bool {
return ((
x.size() == 0) || ...); }, *
mTables)) {
170 if (((tables.size() == 0) || ...)) {
174 template <
typename... Tss>
178 mTables = std::make_shared<std::tuple<Tss...>>(std::make_tuple(std::move(tables)...));
181 std::apply([](
auto&&...
x) ->
bool {
return ((
x.size() == 0) || ...); }, *
mTables)) {
188 constexpr auto k =
sizeof...(Ts);
189 for_<k>([&,
this](
auto i) {
203template <
typename...
Ts>
206template <
typename...
Ts>
209template <
typename...
Ts>
219 constexpr auto k =
sizeof...(Ts);
221 for_<k>([&,
this](
auto i) {
223 constexpr auto curInd = k -
i.value - 1;
225 if (*std::get<1>(std::get<curInd>(this->
mCurrent).getIndices()) != std::get<curInd>(this->
mMaxOffset)) {
227 for_<
i.value>([&,
this](
auto j) {
228 constexpr auto curJ = k -
i.value +
j.value;
229 int64_t nextInd = *std::get<1>(std::get<curJ - 1>(this->
mCurrent).getIndices());
230 if (nextInd < std::get<curJ>(this->
mMaxOffset)) {
231 std::get<curJ>(this->
mCurrent).setCursor(nextInd);
243template <
typename...
Ts>
274 constexpr auto k =
sizeof...(Ts);
275 if (((tables.size() < k) || ...)) {
279 for_<k>([&,
this](
auto i) {
281 std::get<
i.value>(this->
mCurrent).moveByIndex(
i.value);
286 constexpr auto k =
sizeof...(Ts);
288 std::apply([](
auto&&...
x) ->
bool {
return ((
x.size() < k) || ...); }, *this->
mTables)) {
292 for_<k>([&,
this](
auto i) {
294 std::get<
i.value>(this->
mCurrent).moveByIndex(
i.value);
300 constexpr auto k =
sizeof...(Ts);
302 for_<k>([&,
this](
auto i) {
304 constexpr auto curInd = k -
i.value - 1;
306 if (*std::get<1>(std::get<curInd>(this->
mCurrent).getIndices()) != std::get<curInd>(this->
mMaxOffset)) {
308 for_<
i.value>([&,
this](
auto j) {
309 constexpr auto curJ = k -
i.value +
j.value;
310 int64_t nextInd = *std::get<1>(std::get<curJ - 1>(this->
mCurrent).getIndices()) + 1;
311 if (nextInd < std::get<curJ>(this->
mMaxOffset)) {
312 std::get<curJ>(this->
mCurrent).setCursor(nextInd);
324template <
typename...
Ts>
334 constexpr auto k =
sizeof...(Ts);
336 for_<k>([&,
this](
auto i) {
338 constexpr auto curInd = k -
i.value - 1;
340 if (*std::get<1>(std::get<curInd>(this->
mCurrent).getIndices()) != std::get<curInd>(this->
mMaxOffset)) {
341 for_<
i.value>([&,
this](
auto j) {
342 constexpr auto curJ = k -
i.value +
j.value;
343 std::get<curJ>(this->
mCurrent).setCursor(0);
354template <
typename BP,
typename T,
typename...
Ts>
386 constexpr auto k =
sizeof...(Ts);
398 for (
int i = 0;
i < k;
i++) {
405 for_<k>([
this](
auto i) {
411 constexpr auto k =
sizeof...(Ts);
421 std::apply([&,
this](
auto&&...
x)
mutable {
429 for (
int i = 0;
i < k;
i++) {
436 for_<k>([
this](
auto i) {
452 uint64_t maxForTable = std::get<0>(this->
mMaxOffset);
453 uint64_t currentMax = maxForWindow < maxForTable ? maxForWindow : maxForTable;
472template <
typename BP,
typename T,
typename...
Ts>
503 constexpr auto k =
sizeof...(Ts);
504 for_<k>([&,
this](
auto i) {
515 constexpr auto k =
sizeof...(Ts);
517 bool nextCatAvailable =
true;
518 for_<k - 1>([&,
this](
auto i) {
520 constexpr auto curInd = k -
i.value - 1;
526 if (curGroupedInd < maxForWindow && curGroupedInd < std::get<curInd>(this->
mMaxOffset)) {
529 for_<
i.value>([&,
this](
auto j) {
530 constexpr auto curJ = k -
i.value +
j.value;
552 if (curGroupedInd < std::get<0>(this->
mMaxOffset)) {
555 for_<k - 1>([&,
this](
auto j) {
556 constexpr auto curJ =
j.value + 1;
571 for_<k>([&,
this](
auto m) {
574 nextCatAvailable =
false;
577 if (nextCatAvailable) {
582 this->
mIsEnd = modify && !nextCatAvailable;
586template <
typename BP,
typename T,
typename...
Ts>
618 constexpr auto k =
sizeof...(Ts);
619 for_<k>([&,
this](
auto i) {
630 constexpr auto k =
sizeof...(Ts);
632 bool nextCatAvailable =
true;
633 for_<k>([&,
this](
auto i) {
635 constexpr auto curInd = k -
i.value - 1;
639 uint64_t maxForWindow = std::get<curInd>(this->
mBeginIndices) + windowOffset;
642 if (curGroupedInd < maxForWindow && curGroupedInd < std::get<curInd>(this->
mMaxOffset)) {
644 for_<
i.value>([&,
this](
auto j) {
645 constexpr auto curJ = k -
i.value +
j.value;
666 for_<k>([&,
this](
auto s) {
667 if (s.value < this->mCurrentlyFixed) {
668 std::get<s.value>(this->mCurrentIndices) = std::get<s.value>(this->mBeginIndices) + 1;
670 std::get<s.value>(this->mCurrentIndices) = std::get<s.value>(this->mBeginIndices);
672 uint64_t curGroupedI = std::get<s.value>(this->mCurrentIndices);
686 for_<k - 1>([&,
this](
auto j) {
687 constexpr auto curJ =
j.value + 1;
703 for_<k>([&,
this](
auto m) {
706 nextCatAvailable =
false;
709 if (nextCatAvailable) {
714 this->
mIsEnd = modify && !nextCatAvailable;
720template <
typename BP,
typename T1,
typename T,
typename...
Ts>
725 CombinationsBlockSameIndexPolicyBase(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
int minWindowSize) :
CombinationsIndexPolicyBase<T,
Ts...>(),
mSlidingWindowSize(categoryNeighbours + 1),
mBP(binningPolicy),
mCategoryNeighbours(categoryNeighbours),
mOutsider(outsider),
mMinWindowSize(minWindowSize),
mIsNewWindow(true) {}
726 CombinationsBlockSameIndexPolicyBase(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
int minWindowSize,
const T& table,
const Ts&... tables) :
CombinationsIndexPolicyBase<T,
Ts...>(table, tables...),
mSlidingWindowSize(categoryNeighbours + 1),
mBP(binningPolicy),
mCategoryNeighbours(categoryNeighbours),
mOutsider(outsider),
mMinWindowSize(minWindowSize),
mIsNewWindow(true)
732 CombinationsBlockSameIndexPolicyBase(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
int minWindowSize, T&& table,
Ts&&... tables) :
CombinationsIndexPolicyBase<T,
Ts...>(
std::forward<T>(table),
std::forward<
Ts>(tables)...),
mSlidingWindowSize(categoryNeighbours + 1),
mBP(binningPolicy),
mCategoryNeighbours(categoryNeighbours),
mOutsider(outsider),
mMinWindowSize(minWindowSize),
mIsNewWindow(true)
756 constexpr auto k =
sizeof...(Ts) + 1;
774 constexpr auto k =
sizeof...(Ts) + 1;
802 uint64_t maxForTable = std::get<0>(this->
mMaxOffset);
803 uint64_t currentMax = maxForWindow < maxForTable ? maxForWindow : maxForTable;
822template <
typename BP,
typename T1,
typename...
Ts>
853 constexpr auto k =
sizeof...(Ts);
858 for_<k>([&,
this](
auto i) {
867 constexpr auto k =
sizeof...(Ts);
869 for_<k - 1>([&,
this](
auto i) {
871 constexpr auto curInd = k -
i.value - 1;
877 if (curGroupedInd < maxForWindow && curGroupedInd < std::get<curInd>(this->
mMaxOffset)) {
879 for_<
i.value>([&,
this](
auto j) {
880 constexpr auto curJ = k -
i.value +
j.value;
898 if (curGroupedInd < std::get<0>(this->
mMaxOffset)) {
900 for_<k - 1>([&,
this](
auto j) {
901 constexpr auto curJ =
j.value + 1;
920template <
typename BP,
typename T1,
typename...
Ts>
956 constexpr auto k =
sizeof...(Ts);
959 uint64_t lastOffset = std::distance(this->
mGroupedIndices.begin(), lastIt);
961 for_<k>([&,
this](
auto i) {
964 std::get<
i.value>(this->
mMaxOffset) = lastOffset - k +
i.value + 1;
970 constexpr auto k =
sizeof...(Ts);
972 for_<k - 1>([&,
this](
auto i) {
974 constexpr auto curInd = k -
i.value - 1;
980 if (curGroupedInd < maxForWindow && curGroupedInd < std::get<curInd>(this->
mMaxOffset)) {
982 for_<
i.value>([&,
this](
auto j) {
983 constexpr auto curJ = k -
i.value +
j.value;
1001 if (curGroupedInd < std::get<0>(this->
mMaxOffset)) {
1003 for_<k - 1>([&,
this](
auto j) {
1004 constexpr auto curJ =
j.value + 1;
1015 for_<k>([&,
this](
auto m) {
1026template <
typename BP,
typename T1,
typename...
Ts>
1031 CombinationsBlockFullSameIndexPolicy(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
const Ts&... tables) :
CombinationsBlockSameIndexPolicyBase<BP, T1,
Ts...>(binningPolicy, categoryNeighbours, outsider, 1, tables...),
mCurrentlyFixed(0)
1037 CombinationsBlockFullSameIndexPolicy(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
Ts&&... tables) :
CombinationsBlockSameIndexPolicyBase<BP, T1,
Ts...>(binningPolicy, categoryNeighbours, outsider, 1,
std::forward<
Ts>(tables)...),
mCurrentlyFixed(0)
1057 constexpr auto k =
sizeof...(Ts);
1063 for_<k>([&,
this](
auto i) {
1072 constexpr auto k =
sizeof...(Ts);
1074 for_<k>([&,
this](
auto i) {
1076 constexpr auto curInd = k -
i.value - 1;
1080 uint64_t maxForWindow = this->
mBeginIndex + windowOffset;
1083 if (curGroupedInd < maxForWindow && curGroupedInd < std::get<curInd>(this->
mMaxOffset)) {
1085 for_<
i.value>([&,
this](
auto j) {
1086 constexpr auto curJ = k -
i.value +
j.value;
1105 for_<k>([&,
this](
auto s) {
1106 if (s.value < this->mCurrentlyFixed) {
1107 std::get<s.value>(this->mCurrentIndices) = this->mBeginIndex + 1;
1109 std::get<s.value>(this->mCurrentIndices) = this->mBeginIndex;
1111 uint64_t curGroupedI = std::get<s.value>(this->mCurrentIndices);
1124 for_<k - 1>([&,
this](
auto j) {
1125 constexpr auto curJ =
j.value + 1;
1132 for_<k>([&,
this](
auto j) {
1154template <
typename P>
1177 if (!this->mIsEnd) {
1192 return this->mCurrent;
1196 return (lh.mIsEnd && rh.mIsEnd) || (lh.mCurrent == rh.mCurrent);
1232template <
typename T2,
typename... T2s>
1235 return (std::same_as<T2, T2s> && ...);
1238template <
typename BP,
typename T1,
typename... T2s>
1239auto selfCombinations(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
const T2s&... tables)
1241 static_assert(
isSameType<T2s...>(),
"Tables must have the same type for self combinations");
1245template <
typename BP,
typename T1,
typename T2>
1251template <
typename BP,
typename T1,
typename T2>
1254 return CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, T2, T2>>(
CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, T2, T2>(binningPolicy, categoryNeighbours, outsider, table, table));
1257template <
typename BP,
typename T1,
typename T2>
1260 return CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, T2, T2, T2>>(
CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, T2, T2, T2>(binningPolicy, categoryNeighbours, outsider));
1263template <
typename BP,
typename T1,
typename T2>
1266 return CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, T2, T2, T2>>(
CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, T2, T2, T2>(binningPolicy, categoryNeighbours, outsider, table, table, table));
1269template <
typename BP,
typename T1,
typename... T2s>
1270auto combinations(
const BP& binningPolicy,
int categoryNeighbours,
const T1& outsider,
const T2s&... tables)
1279template <
typename BP,
typename T1,
typename... T2s>
1301template <
template <
typename...>
typename P2,
typename... T2s>
1307template <
template <
typename...>
typename P2,
soa::is_table... T2s>
1313template <
typename... T2s>
1323template <
typename T2>
1329template <
typename T2>
1335template <
typename T2>
1341template <
typename T2>
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum GLenum type
GLenum GLsizei GLsizei GLint * values
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLboolean GLboolean GLboolean GLboolean a
constexpr bool isSameType()
bool diffCategory(BinningIndex const &a, BinningIndex const &b)
void syncCategories(std::array< std::vector< BinningIndex >, K > &groupedIndices)
auto selfTripleCombinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
auto tripleCombinations()
std::vector< BinningIndex > groupTable(const T &table, const BP< Cs... > &binningPolicy, int minCatSize, int outsider)
auto combinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const T2s &... tables)
auto selfCombinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const T2s &... tables)
void for_(F func, std::index_sequence< Is... >)
auto selfPairCombinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
void dataSizeVariesBetweenColumns()
bool sameCategory(BinningIndex const &a, BinningIndex const &b)
Defining DataPointCompositeObject explicitly as copiable.
A struct, containing the root of the expression tree.
bool operator<(const BinningIndex &rhs) const
BinningIndex(int bin_, uint64_t index_)
CombinationsBlockFullIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T &outsider, Ts &&... tables)
typename CombinationsBlockIndexPolicyBase< BP, T, Ts... >::CombinationType CombinationType
CombinationsBlockFullIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T &outsider, const Ts &... tables)
void setTables(const Ts &... tables)
CombinationsBlockFullIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T &outsider)
void setTables(Ts &&... tables)
typename NTupleType< uint64_t, sizeof...(Ts)>::type IndicesType
void setTables(Ts &&... tables)
void setTables(const Ts &... tables)
CombinationsBlockFullSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, Ts &&... tables)
CombinationsBlockFullSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
CombinationsBlockFullSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const Ts &... tables)
typename CombinationsBlockSameIndexPolicyBase< BP, T1, Ts... >::CombinationType CombinationType
std::array< std::vector< BinningIndex >, sizeof...(Ts)> mGroupedIndices
const int mCategoryNeighbours
void setRanges(const Ts &... tables)
void setTables(Ts &&... tables)
typename CombinationsIndexPolicyBase< Ts... >::CombinationType CombinationType
CombinationsBlockIndexPolicyBase(const BP &binningPolicy, int categoryNeighbours, const T &outsider, const Ts &... tables)
IndicesType mBeginIndices
void setRanges(Ts &&... tables)
uint64_t mSlidingWindowSize
CombinationsBlockIndexPolicyBase(const BP &binningPolicy, int categoryNeighbours, const T &outsider)
int currentWindowNeighbours()
void setTables(const Ts &... tables)
typename NTupleType< uint64_t, sizeof...(Ts)>::type IndicesType
CombinationsBlockIndexPolicyBase(const BP &binningPolicy, int categoryNeighbours, const T &outsider, Ts &&... tables)
IndicesType mCurrentIndices
CombinationsBlockSameIndexPolicyBase(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, int minWindowSize)
void setTables(T &&table, Ts &&... tables)
CombinationsBlockSameIndexPolicyBase(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, int minWindowSize, const T &table, const Ts &... tables)
void setTables(const T &table, const Ts &... tables)
CombinationsBlockSameIndexPolicyBase(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, int minWindowSize, T &&table, Ts &&... tables)
IndicesType mCurrentIndices
std::vector< BinningIndex > mGroupedIndices
void setRanges(const T &table)
const int mCategoryNeighbours
typename CombinationsIndexPolicyBase< T, Ts... >::CombinationType CombinationType
int currentWindowNeighbours()
const uint64_t mSlidingWindowSize
typename NTupleType< uint64_t, sizeof...(Ts)+1 >::type IndicesType
CombinationsBlockStrictlyUpperSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, Ts &&... tables)
void setTables(Ts &&... tables)
void setTables(const Ts &... tables)
CombinationsBlockStrictlyUpperSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const Ts &... tables)
CombinationsBlockStrictlyUpperSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
typename CombinationsBlockSameIndexPolicyBase< BP, T1, Ts... >::CombinationType CombinationType
CombinationsBlockUpperIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T &outsider, Ts &&... tables)
void setTables(Ts &&... tables)
CombinationsBlockUpperIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T &outsider, const Ts &... tables)
void setTables(const Ts &... tables)
typename CombinationsBlockIndexPolicyBase< BP, T, Ts... >::CombinationType CombinationType
CombinationsBlockUpperIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T &outsider)
void setTables(Ts &&... tables)
CombinationsBlockUpperSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, Ts &&... tables)
CombinationsBlockUpperSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const Ts &... tables)
void setTables(const Ts &... tables)
CombinationsBlockUpperSameIndexPolicy(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
typename CombinationsBlockSameIndexPolicyBase< BP, T1, Ts... >::CombinationType CombinationType
CombinationsFullIndexPolicy(Ts &&... tables)
CombinationsFullIndexPolicy()
typename CombinationsIndexPolicyBase< Ts... >::CombinationType CombinationType
CombinationsFullIndexPolicy(const Ts &... tables)
CombinationType value_type
CombinationsIterator & operator++()
~CombinationsIterator()=default
CombinationType & reference
CombinationsIterator operator++(int)
CombinationsIterator(CombinationsIterator const &)=default
CombinationsIterator & operator=(CombinationsIterator const &)=default
std::forward_iterator_tag iterator_category
CombinationsIterator()=delete
CombinationType * pointer
friend bool operator==(const CombinationsIterator &lh, const CombinationsIterator &rh)
CombinationsIterator(const P &policy)
const_iterator begin() const
const_iterator end() const
~CombinationsGenerator()=default
CombinationsGenerator(const P &policy)
CombinationsIterator iterator
CombinationsGenerator()=delete
typename P::CombinationType CombinationType
std::shared_ptr< std::tuple< Ts... > > mTables
CombinationsIndexPolicyBase()
CombinationsIndexPolicyBase(Tss &&... tables)
void setTables(const Ts &... tables)
typename NTupleType< uint64_t, sizeof...(Ts)>::type IndicesType
void setTables(Tss &&... tables)
CombinationsIndexPolicyBase(const Tss &... tables)
std::tuple< typename Ts::iterator... > CombinationType
typename CombinationsIndexPolicyBase< Ts... >::CombinationType CombinationType
void setTables(const Ts &... tables)
void setRanges(const Ts &... tables)
void setTables(Ts &&... tables)
CombinationsStrictlyUpperIndexPolicy()
CombinationsStrictlyUpperIndexPolicy(Ts &&... tables)
CombinationsStrictlyUpperIndexPolicy(const Ts &... tables)
typename CombinationsIndexPolicyBase< Ts... >::CombinationType CombinationType
CombinationsUpperIndexPolicy(Ts &&... tables)
CombinationsUpperIndexPolicy()
CombinationsUpperIndexPolicy(const Ts &... tables)
std::tuple< REST... > type
typename NTupleType< T, N - 1, T, REST... >::type type