-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcustom.hpp
102 lines (75 loc) · 3.62 KB
/
custom.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
#error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY
//==================================================================================================
/**
\page custom Tutorial: Customizing Keyword
@tableofcontents
\section custom_01 Using Pre-bound keyword
Sometimes you wish you could have a terser syntax for keyword parameters.
Let's say you want to pass a compile-time unrolling factor to some algorithm.
@code
// This is working but a bit verbose
using namespace rbr::literals;
inline constexpr auto unroll = rbr::keyword("unrolling"_id);
auto x = my_algorithm( unroll = std::integral_constant<int,4>{});
@endcode
One idea is to defines a **pre-bound keyword parameter**, i.e constructs an inline
variable initialized with the result of the assignment of a value to a keyword.
@code
using namespace rbr::literals;
inline constexpr auto unrolling = rbr::keyword("unrolling"_id);
template<int N> inline constexpr auto unroll = (unrolling = std::integral_constant<int,N>{});
@endcode
`unroll<N>` is now ready to be passed around. To retrieve it, you'll need to use
the `unrolling` keyword.
@include doc/tutorial04.cpp
\section custom_02 Custom RABERU Keywords
The keywords provided by **RABERU** can also be extended to propose a better user experience.
This includes using user-defined type instead of **RABERU** long symbol to improve diagnostic
, complex checks or provide custom display when using stream insertion of settings.
\subsection custom-extension Extending RABERU Keywords
Let's start again with our unrolling option. This time we want to be able to be sure nobody
will use it with a non integral constant value and to display the value in a more informative way.
To do so, we can inherits from `rbr::as_keyword`, a CRTP enabled base class:
@code
struct unrolling : rbr::as_keyword<unrolling>
{
template<int N>
constexpr auto operator=(std::integral_constant<int,N> const&) const noexcept
{
return rbr::option<unrolling,std::integral_constant<int,N>>{};
}
std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; }
};
template<int N> inline constexpr auto unroll = (unrolling{} = std::integral_constant<int,N>{});
@endcode
What if we call `f( unrolling{} = 3.f );` ? Well, we go this error message:
@code
example.cpp:25:18: error: no viable overloaded '='
f( unrolling{} = 3.f );
~~~~~~~~~~~ ^ ~~~
<source>:8:18: note: candidate template ignored: could not match 'integral_constant<int, N>' against 'float'
constexpr auto operator=(std::integral_constant<int,N> const&) const noexcept
@endcode
\subsection custom-display Custom Keywords Display
Let's now improve the output of the option. Currently, the output is like:
@code
[unrolling] : 8 (std::integral_constant<int, 8>)
@endcode
A bit verbose especially for end-user.
Keyword-like entity can specialize a `display` member function to replace this output by a custom one.
@code
struct unrolling : rbr::as_keyword<unrolling>
{
template<int N>
constexpr auto operator=(std::integral_constant<int,N> const&) const noexcept
{
return rbr::option<unrolling,std::integral_constant<int,N>>{};
}
std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; }
};
@endcode
The `display` member takes the output stream and the actual value of the option to be displayed.
One can then arrange those as they see fit, leading to a better output:
@include doc/tutorial05.cpp
**/
//==================================================================================================