/
transform.hpp
116 lines (96 loc) · 3.7 KB
/
transform.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*==================================================================================================
Copyright (c) 2015 Edouard Alligand and Joel Falcou
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
=================================================================================================**/
#pragma once
#include <brigand/functions/lambda/apply.hpp>
#include <brigand/sequences/back.hpp>
#include <brigand/sequences/filled_list.hpp>
#include <brigand/sequences/size.hpp>
namespace brigand
{
namespace detail
{
template<class L1, class L2>
struct rot90;
template<
class... L1,
template<class...> class S1, class... T1,
template<class...> class S2, class... T2,
template<class...> class S3, class... T3,
template<class...> class S4, class... T4,
template<class...> class S5, class... T5,
template<class...> class S6, class... T6,
template<class...> class S7, class... T7,
template<class...> class S8, class... T8,
class... L2>
struct rot90<list<L1...>, list<
S1<T1...>, S2<T2...>, S3<T3...>, S4<T4...>,
S5<T5...>, S6<T6...>, S7<T7...>, S8<T8...>, L2...>>
: rot90<list<push_back<L1, T1, T2, T3, T4, T5, T6, T7, T8>...>, list<L2...>>
{};
template<class... L1, template<class...> class S, class... T, class... L2>
struct rot90<list<L1...>, list<S<T...>, L2...>>
: rot90<list<push_back<L1, T>...>, list<L2...>>
{};
template<class L1>
struct rot90<L1, list<>>
{
using type = L1;
};
template<class Func, class Seq1, class Seq2, class Seqs>
struct transform_impl;
template<class F, class T1, class T2, class Seq>
struct transform_apply;
template<class F, class T1, class T2, class... Ts>
struct transform_apply<F, T1, T2, list<Ts...>>
{
using type = brigand::apply<F, T1, T2, Ts...>;
};
template<
class Func,
template<class...> class Seq1, class... T1,
template<class...> class Seq2, class... T2,
class... Seqs>
struct transform_impl<Func, Seq1<T1...>, Seq2<T2...>, list<Seqs...>>
{
using type = Seq1<typename transform_apply<Func, T1, T2, Seqs>::type...>;
};
template<std::size_t N, class Seq1, class Seq2, class... FuncOrSeqs>
struct transform
: transform_impl<back<list<FuncOrSeqs...>>, Seq1, Seq2,
typename rot90<filled_list<list<>, size<Seq1>::value>, pop_back<list<FuncOrSeqs...>>>::type>
{};
template<template<class...> class Seq, class... T, class Func>
struct transform<0, Seq<T...>, Func>
{
using type = Seq<brigand::apply<Func, T>...>;
};
//fast track for eager
template<template<class...> class Seq, class... T, template<typename...> class Func>
struct transform<0, Seq<T...>, bind<Func, _1>>
{
using type = Seq<Func<T>...>;
};
//fast track for lazy
template<template<class...> class Seq, class... T, template<typename...> class Func>
struct transform<0, Seq<T...>, Func<_1>>
{
using type = Seq<typename Func<T>::type...>;
};
template<template<class...> class Seq1, class... T1, template<class...> class Seq2, class... T2, class Func>
struct transform<1, Seq1<T1...>, Seq2<T2...>, Func>
{
using type = Seq1<brigand::apply<Func, T1, T2>...>;
};
}
namespace lazy
{
template<typename Sequence1, typename OpSeq1, typename... OpSeq2>
struct transform : detail::transform<sizeof...(OpSeq2), Sequence1, OpSeq1, OpSeq2...> {};
}
// Main transform entry point
template<typename Sequence1, typename OpSeq1, typename... OpSeq2>
using transform = typename detail::transform<sizeof...(OpSeq2), Sequence1, OpSeq1, OpSeq2...>::type;
}