CNL  2.0.2 (development)
Compositional Numeric Library
constant.h
Go to the documentation of this file.
1 
2 // Copyright John McFarlane 2015 - 2017.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file ../LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
9 
10 #if !defined(CNL_CONSTANT_H)
11 #define CNL_CONSTANT_H
12 
13 #include "_impl/config.h"
14 #include "_impl/cstdint/types.h"
15 #include "_impl/num_traits/digits.h"
16 #include "_impl/numbers/signedness.h"
17 #include "_impl/parse.h"
18 #include "integer.h"
19 
20 #include <limits>
21 #include <type_traits>
22 
23 // CNL_IMPL_CONSTANT_VALUE_TYPE - determines cnl::constant<>::value_type
24 #if defined(CNL_TEMPLATE_AUTO)
25 // If template<auto> feature is available, cnl::constant's value can be any type.
26 #define CNL_IMPL_CONSTANT_VALUE_TYPE auto // NOLINT(cppcoreguidelines-macro-usage)
27 #else
28 // Otherwise it is defaulted to the widest quantity type that can be used as a template argument.
29 #define CNL_IMPL_CONSTANT_VALUE_TYPE ::cnl::intmax_t // NOLINT(cppcoreguidelines-macro-usage)
30 #endif
31 
33 namespace cnl {
34 
36  // cnl::constant - expresses a value as a type
37 
42 
43  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value>
44  struct constant {
45 #if defined(CNL_TEMPLATE_AUTO)
46  using value_type = decltype(Value);
47 #else
48  using value_type = CNL_IMPL_CONSTANT_VALUE_TYPE;
49 #endif
50 
51  static constexpr value_type value = Value;
52 
53  constexpr constant() = default;
54 
55  template<typename S>
56  constexpr explicit constant(S const& init)
57  {
58  static_assert(
60  && value >= std::numeric_limits<S>::lowest(),
61  "initial value couldn't possibly represent value");
62  CNL_ASSERT(value == init);
63  }
64 
65 #if defined(_MSC_VER) && _MSC_VER < 1924
66  // NOLINTNEXTLINE(hicpp-explicit-conversions, google-explicit-constructor)
67  [[nodiscard]] constexpr operator auto() const -> value_type
68  {
69  return value;
70  }
71 #else
72  // NOLINTNEXTLINE(hicpp-explicit-conversions, google-explicit-constructor)
73  [[nodiscard]] constexpr operator value_type() const
74  {
75  return value;
76  }
77 #endif
78  };
79 
81  // cnl::constant operator overloads
82 
83 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
84 #define CNL_IMPL_CONSTANT_UNARY(OPERATOR) \
85  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value> \
86  [[nodiscard]] constexpr auto operator OPERATOR( \
87  constant<Value>) noexcept->constant<OPERATOR Value> \
88  { \
89  return constant<OPERATOR Value>{}; \
90  }
91 
92 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
93 #define CNL_IMPL_CONSTANT_BINARY(OPERATOR) \
94  template<CNL_IMPL_CONSTANT_VALUE_TYPE LhsValue, CNL_IMPL_CONSTANT_VALUE_TYPE RhsValue> \
95  [[nodiscard]] constexpr auto operator OPERATOR( \
96  constant<LhsValue>, \
97  constant<RhsValue>) noexcept->constant<(LhsValue OPERATOR RhsValue)> \
98  { \
99  return constant<(LhsValue OPERATOR RhsValue)>{}; \
100  }
101 
102  // arithmetic
103  CNL_IMPL_CONSTANT_UNARY(+)
104  CNL_IMPL_CONSTANT_UNARY(-)
105  CNL_IMPL_CONSTANT_BINARY(+)
106  CNL_IMPL_CONSTANT_BINARY(-)
107  CNL_IMPL_CONSTANT_BINARY(*)
108  CNL_IMPL_CONSTANT_BINARY(/)
109  CNL_IMPL_CONSTANT_BINARY(%)
110  CNL_IMPL_CONSTANT_UNARY(~)
111  CNL_IMPL_CONSTANT_BINARY(&)
112  CNL_IMPL_CONSTANT_BINARY(|)
113  CNL_IMPL_CONSTANT_BINARY(^)
114  CNL_IMPL_CONSTANT_BINARY(<<)
115  CNL_IMPL_CONSTANT_BINARY(>>)
116 
117  // logical
118  CNL_IMPL_CONSTANT_UNARY(!)
119  CNL_IMPL_CONSTANT_BINARY(&&)
120  CNL_IMPL_CONSTANT_BINARY(||)
121 
122  // comparison
123  CNL_IMPL_CONSTANT_BINARY(==)
124  CNL_IMPL_CONSTANT_BINARY(!=)
125  CNL_IMPL_CONSTANT_BINARY(<)
126  CNL_IMPL_CONSTANT_BINARY(>)
127  CNL_IMPL_CONSTANT_BINARY(<=)
128  CNL_IMPL_CONSTANT_BINARY(>=)
129 
130  namespace _impl {
132  // cnl::_impl::is_constant type traits
133 
134  template<class T>
135  struct is_constant : std::false_type {
136  };
137 
138  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value>
139  struct is_constant<::cnl::constant<Value>> : std::true_type {
140  };
141 
142  template<typename T>
143  inline constexpr auto is_constant_v = is_constant<T>::value;
144  }
145 
147  // cnl::literals - literal wrapper for constant
148  //
149  // http://codereview.stackexchange.com/a/51576/26421
150 
151  namespace literals {
152  template<char... Chars>
153  [[nodiscard]] constexpr auto operator"" _c()
154  -> constant<_impl::parse<intmax_t, Chars...>()>
155  {
156  return {};
157  }
158  }
159 
161  // numeric traits
162 
163  template<auto Value>
164  inline constexpr int digits_v<constant<Value>> = _impl::used_digits((Value < 0) ? -Value : Value);
165 
167  // numbers traits
168 
169  namespace numbers {
170  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value>
171  struct signedness<constant<Value>> : signedness<decltype(Value)> {
172  };
173  }
174 
176  // concepts
177 
178  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value>
179  struct is_integer<constant<Value>> : is_integer<decltype(Value)> {
180  };
181 
182  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value>
183  struct is_integer<constant<Value> const> : is_integer<decltype(Value)> {
184  };
185 }
186 
187 namespace std {
189  // std::numeric_limits<cnl::constant>
190 
191  template<CNL_IMPL_CONSTANT_VALUE_TYPE Value>
192  struct numeric_limits<cnl::constant<Value>>
193  : numeric_limits<typename cnl::constant<Value>::value_type> {
194  private:
195  using value_type = typename cnl::constant<Value>::value_type;
196 
197  public:
198  [[nodiscard]] static constexpr auto min()
199  {
200  return value_type{};
201  }
202 
203  [[nodiscard]] static constexpr auto max()
204  {
205  return value_type{};
206  }
207 
208  [[nodiscard]] static constexpr auto lowest()
209  {
210  return value_type{};
211  }
212  };
213 }
214 
215 #endif // CNL_CONSTANT_H
std::false_type
types.h
fixed-width integer types equivalent to those in
std::numeric_limits::lowest
T lowest(T... args)
cnl
compositional numeric library
Definition: abort.h:15
std::numeric_limits::min
T min(T... args)
std
STL namespace.
config.h
definitions which can be used to configure CNL library
cnl::constant
type whose value is also its non-type template parameter
Definition: constant.h:44
std::numeric_limits::max
T max(T... args)
std::numeric_limits