Skip to content

Commit 02d2564

Browse files
Merge pull request #6 from contour-terminal/improvement/new_advanced_example
Update advance example
2 parents b7885c7 + ee33505 commit 02d2564

File tree

2 files changed

+136
-24
lines changed

2 files changed

+136
-24
lines changed

README.md

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,46 +63,70 @@ double value_d = speed_of_light * 2.0;
6363

6464

6565
# More advanced usage
66-
You can forget about the order of parameters in your code
66+
You can forget about the order of parameters in your code. Complete code see: [godbolt](https://godbolt.org/z/K8fqjqs34)
6767

6868
``` c++
69-
#include <boxed-cpp/boxed.hpp>
69+
namespace Tag{ struct Rho{}; struct Theta{}; struct Phi{};}
7070

71-
// Create unique structures
72-
namespace tags { struct Speed{}; struct Permittivity{}; struct Permeability{}; }
71+
using rho_type = boxed::boxed<double,Tag::Rho>;
72+
using theta_type = boxed::boxed<double,Tag::Theta>;
73+
using phi_type = boxed::boxed<double,Tag::Phi>;
7374

74-
using Speed = boxed::boxed<double, tags::Speed>;
75-
using Permittivity = boxed::boxed<double, tags::Permittivity>;
76-
using Permeability = boxed::boxed<double, tags::Permeability>;
7775

78-
Speed wave_speed_inside(Permittivity epsilon, Permeability mu)
79-
{
80-
return Speed(1.0 / std::sqrt(unbox(epsilon) * unbox(mu)));
81-
};
76+
template<typename ...T>
77+
struct Wrap{};
8278

83-
template <typename T, typename S>
84-
Speed wave_speed(T t, S s) // recursive variadic function
79+
template<typename T, typename ...Rest>
80+
struct Wrap<T, Rest ...>
8581
{
86-
if constexpr (std::is_same_v<T, Permittivity>)
82+
83+
constexpr static inline std::size_t n = 1 + sizeof...(Rest);
84+
using fun_type = std::function<double(T)>;
85+
Wrap(fun_type&& first, std::function<double(Rest)>&& ...rest)
86+
: first(std::forward<fun_type>(first))
87+
, rest(std::forward<std::function<double(Rest)>>(rest)...)
88+
{}
89+
90+
const fun_type first;
91+
Wrap<Rest...> rest;
92+
93+
auto operator()(T v)
8794
{
88-
return wave_speed_inside(t, s);
95+
return first(v);
8996
}
90-
else
97+
98+
template<typename F>
99+
requires (!std::is_same_v<T,F>)
100+
decltype(auto) operator()(F v)
91101
{
92-
return wave_speed_inside(s, t);
102+
return rest(v);
93103
}
94-
}
104+
105+
106+
template<typename ...Args>
107+
requires (!std::derived_from<all_different<typename std::decay<Args>::type...>, std::false_type>)
108+
decltype(auto) operator()(Args &&... args)
109+
{
110+
static_assert( (sizeof...(Args) == n) );
111+
return ( operator()(std::forward<Args>(args)) * ... );
112+
}
113+
};
114+
115+
auto x_coord = Wrap<rho_type,theta_type,phi_type>{
116+
[](rho_type rho){ return unbox(rho); },
117+
[](theta_type theta){ return sin(unbox(theta)); },
118+
[](phi_type phi){ return cos(unbox(phi)); }
119+
};
95120

96121

97122
int main()
98123
{
99-
constexpr auto vacuum_permittivity = Permittivity(8.85418781762039e-12);
100-
constexpr auto pi = 3.14159265358979323846;
101-
constexpr auto vacuum_permeability = Permeability(4 * pi * 1e-7);
124+
rho_type rho{1.0};
125+
theta_type theta{3.14 / 3.0};
126+
phi_type phi{3.14/2.0};
102127

103-
auto speed_one = wave_speed(vacuum_permittivity, vacuum_permeability);
104-
auto speed_two = wave_speed(vacuum_permeability, vacuum_permittivity);
105-
// speed_one == speed_two
128+
assert(x_coord(rho,theta,phi) == x_coord(theta,rho,phi));
129+
assert(x_coord(rho,theta,phi) == x_coord(phi,rho,theta));
106130
}
107131
```
108132

test-boxed-cpp.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,91 @@ TEST_CASE("all options for unbox")
118118
REQUIRE(unbox<float>(speed_of_light));
119119
REQUIRE(unbox(speed_of_light));
120120
}
121+
122+
// advanced usage test
123+
124+
template<typename ...Ts>
125+
struct not_same{};
126+
127+
template<typename T>
128+
struct not_same<T,T> : virtual std::false_type {};
129+
130+
template<typename T,typename S>
131+
struct not_same<T,S> : virtual std::true_type {} ;
132+
133+
template <typename ...T>
134+
struct all_different : std::false_type {};
135+
136+
template<typename T, typename F>
137+
struct all_different<T,F> : not_same<T,F> {};
138+
139+
template<typename T, typename... Ts>
140+
struct all_different<T,T, Ts...> : virtual std::false_type {};
141+
142+
template<typename T, typename F,typename... Ts>
143+
struct all_different<T,F, Ts...> : all_different<T,Ts...>, all_different<F,Ts...> {};
144+
145+
namespace Tag{ struct Rho{}; struct Theta{}; struct Phi{};}
146+
147+
using rho_type = boxed::boxed<double,Tag::Rho>;
148+
using theta_type = boxed::boxed<double,Tag::Theta>;
149+
using phi_type = boxed::boxed<double,Tag::Phi>;
150+
151+
152+
template<typename ...T>
153+
struct Wrap{};
154+
155+
template<typename T, typename ...Rest>
156+
struct Wrap<T, Rest ...>
157+
{
158+
159+
constexpr static inline std::size_t n = 1 + sizeof...(Rest);
160+
using fun_type = std::function<double(T)>;
161+
Wrap(fun_type&& first, std::function<double(Rest)>&& ...rest)
162+
: first(std::forward<fun_type>(first))
163+
, rest(std::forward<std::function<double(Rest)>>(rest)...)
164+
{}
165+
166+
const fun_type first;
167+
Wrap<Rest...> rest;
168+
169+
auto operator()(T v)
170+
{
171+
return first(v);
172+
}
173+
174+
template<typename F>
175+
requires (!std::is_same_v<T,F>)
176+
decltype(auto) operator()(F v)
177+
{
178+
return rest(v);
179+
}
180+
181+
182+
template<typename ...Args>
183+
requires (!std::derived_from<all_different<typename std::decay<Args>::type...>, std::false_type>)
184+
decltype(auto) operator()(Args &&... args)
185+
{
186+
static_assert( (sizeof...(Args) == n) );
187+
return ( operator()(std::forward<Args>(args)) * ... );
188+
}
189+
};
190+
191+
auto x_coord = Wrap<rho_type,theta_type,phi_type>{
192+
[](rho_type rho){ return unbox(rho); },
193+
[](theta_type theta){ return sin(unbox(theta)); },
194+
[](phi_type phi){ return cos(unbox(phi)); }
195+
};
196+
197+
198+
TEST_CASE("advanced usage")
199+
{
200+
201+
rho_type rho{1.0};
202+
theta_type theta{3.14 / 3.0};
203+
phi_type phi{3.14/2.0};
204+
205+
206+
REQUIRE(x_coord(rho,theta,phi) == x_coord(theta,rho,phi));
207+
REQUIRE(x_coord(rho,theta,phi) == x_coord(phi,rho,theta));
208+
}

0 commit comments

Comments
 (0)