forked from JuliaInterop/CxxWrap.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parametric.cpp
201 lines (167 loc) · 4.56 KB
/
parametric.cpp
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#include <string>
#include <cxx_wrap.hpp>
namespace parametric
{
struct P1
{
typedef int val_type;
static val_type value()
{
return 1;
}
};
struct P2
{
typedef double val_type;
static val_type value()
{
return 10.;
}
};
template<typename A, typename B>
struct TemplateType
{
typedef typename A::val_type first_val_type;
typedef typename B::val_type second_val_type;
first_val_type get_first()
{
return A::value();
}
second_val_type get_second()
{
return B::value();
}
};
// Template containing a non-type parameter
template<typename T, T I>
struct NonTypeParam
{
typedef T type;
NonTypeParam(T v = I) : i(v)
{
}
T i = I;
};
template<typename A, typename B=void>
struct TemplateDefaultType
{
};
template<typename T>
struct AbstractTemplate
{
};
template<typename T>
struct ConcreteTemplate : public AbstractTemplate<T>
{
};
// Helper to wrap TemplateType instances. May also be a C++14 lambda, see README.md
struct WrapTemplateType
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&& wrapped)
{
typedef typename TypeWrapperT::type WrappedT;
wrapped.method("get_first", &WrappedT::get_first);
wrapped.method("get_second", &WrappedT::get_second);
}
};
struct WrapTemplateDefaultType
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&& wrapped)
{
}
};
// Helper to wrap NonTypeParam instances
struct WrapNonTypeParam
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&& wrapped)
{
typedef typename TypeWrapperT::type WrappedT;
wrapped.template constructor<typename WrappedT::type>();
// Access the module to add a free function
wrapped.module().method("get_nontype", [](const WrappedT& w) { return w.i; });
}
};
struct WrapAbstractTemplate
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&&)
{
}
};
struct WrapConcreteTemplate
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&& w)
{
typedef typename TypeWrapperT::type WrappedT;
w.module().method("to_base", [] (WrappedT* w) { return static_cast<AbstractTemplate<double>*>(w); });
}
};
template<typename T1, typename T2, typename T3>
struct Foo3
{
};
struct WrapFoo3
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&& wrapped)
{
typedef typename TypeWrapperT::type WrappedT;
wrapped.module().method("foo3_method", [] (const WrappedT&) {});
}
};
template<typename T1, bool B = false>
struct Foo2
{
};
struct ApplyFoo2
{
template<typename T> using apply = Foo2<T>;
};
struct WrapFoo2
{
template<typename TypeWrapperT>
void operator()(TypeWrapperT&& wrapped)
{
typedef typename TypeWrapperT::type WrappedT;
wrapped.module().method("foo2_method", [] (const WrappedT&) {});
}
};
} // namespace parametric
namespace cxx_wrap
{
// Match type followed by non-type of the same type
template<typename NonTT, NonTT Val, template<typename, NonTT> class T>
struct BuildParameterList<T<NonTT, Val>>
{
typedef ParameterList<NonTT, std::integral_constant<NonTT, Val>> type;
};
template<typename T>
struct BuildParameterList<parametric::Foo2<T>>
{
typedef ParameterList<T> type;
};
} // namespace cxx_wrap
JULIA_CPP_MODULE_BEGIN(registry)
using namespace cxx_wrap;
using namespace parametric;
Module& types = registry.create_module("ParametricTypes");
types.add_type<P1>("P1");
types.add_type<P2>("P2");
types.add_type<Parametric<TypeVar<1>, TypeVar<2>>>("TemplateType")
.apply<TemplateType<P1,P2>, TemplateType<P2,P1>>(WrapTemplateType());
types.add_type<Parametric<TypeVar<1>>>("TemplateDefaultType")
.apply<TemplateDefaultType<P1>, TemplateDefaultType<P2>>(WrapTemplateDefaultType());
types.add_type<Parametric<cxx_wrap::TypeVar<1>, cxx_wrap::TypeVar<2>>>("NonTypeParam")
.apply<NonTypeParam<int, 1>, NonTypeParam<unsigned int, 2>, NonTypeParam<int64_t, 64>>(WrapNonTypeParam());
auto abstract_template = types.add_type<Parametric<cxx_wrap::TypeVar<1>>>("AbstractTemplate");
abstract_template.apply<AbstractTemplate<double>>(WrapAbstractTemplate());
types.add_type<Parametric<cxx_wrap::TypeVar<1>>>("ConcreteTemplate", abstract_template.dt()).apply<ConcreteTemplate<double>>(WrapConcreteTemplate());
types.add_type<Parametric<TypeVar<1>, TypeVar<2>, TypeVar<3>>, ParameterList<TypeVar<1>>>("Foo3", abstract_template.dt())
.apply_combination<Foo3, ParameterList<int32_t, double>, ParameterList<P1,P2,bool>, ParameterList<float>>(WrapFoo3());
types.add_type<Parametric<TypeVar<1>>>("Foo2")
.apply_combination<ApplyFoo2, ParameterList<int32_t, double>>(WrapFoo2());
JULIA_CPP_MODULE_END