|
16 | 16 |
|
17 | 17 | namespace kumi |
18 | 18 | { |
| 19 | + |
| 20 | + namespace _ |
| 21 | + { |
| 22 | + //============================================================================================== |
| 23 | + // Helper concepts for tuple detection |
| 24 | + //============================================================================================== |
| 25 | + // Concept specifying a type is non-empty standard tuple-like type. |
| 26 | + template<typename T> |
| 27 | + concept non_empty_tuple = requires(T const& t) { |
| 28 | + typename std::tuple_element<0, std::remove_cvref_t<T>>::type; |
| 29 | + typename std::tuple_size<std::remove_cvref_t<T>>::type; |
| 30 | + }; |
| 31 | + |
| 32 | + // Concept specifying a type is an empty standard tuple-like type. |
| 33 | + template<typename T> |
| 34 | + concept empty_tuple = (std::tuple_size<std::remove_cvref_t<T>>::value == 0); |
| 35 | + |
| 36 | + //============================================================================================== |
| 37 | + // Helper concepts for container detection |
| 38 | + //============================================================================================== |
| 39 | + // Concept specifying a type is standard container-like type. |
| 40 | + template<typename T> |
| 41 | + concept container_like = requires(T const& t) { |
| 42 | + typename T::value_type; |
| 43 | + typename T::size_type; |
| 44 | + |
| 45 | + { t.size() } -> kumi::convertible_to<std::size_t>; |
| 46 | + { t.begin() }; |
| 47 | + { t.end() }; |
| 48 | + { t.data() }; |
| 49 | + }; |
| 50 | + } |
| 51 | + |
19 | 52 | //================================================================================================ |
20 | 53 | //! @ingroup traits |
21 | 54 | //! @brief Opt-in traits for types behaving like a kumi::product_type |
@@ -177,6 +210,107 @@ namespace kumi |
177 | 210 | template<std::size_t I, typename T> using member_t = typename member<I, T>::type; |
178 | 211 | } |
179 | 212 |
|
| 213 | +namespace kumi |
| 214 | +{ |
| 215 | + //================================================================================================ |
| 216 | + //! @ingroup traits |
| 217 | + //! @brief Traits detecting types behaving like a kumi::static_container. |
| 218 | + //! |
| 219 | + //! To be treated like a static_container, a user defined type must expose a type and a |
| 220 | + //! statically know size encoded in the type. It shall also provide general container utilities. |
| 221 | + //! |
| 222 | + //! @note The type shall be templated on the type and the size to be picked up. |
| 223 | + //! |
| 224 | + //! ## Helper value |
| 225 | + //! @code |
| 226 | + //! template<typename T> inline constexpr auto is_static_container = is_static_container<T>::value; |
| 227 | + //! @endcode |
| 228 | + //! ## Example: |
| 229 | + //============================================================================================== |
| 230 | + template<typename T> struct is_static_container : std::false_type |
| 231 | + { |
| 232 | + }; |
| 233 | + |
| 234 | + template<template<class, std::size_t> typename Container, typename T, std::size_t N> |
| 235 | + requires _::container_like<Container<T, N>> && (N != static_cast<std::size_t>(-1)) |
| 236 | + struct is_static_container<Container<T, N>> : std::true_type |
| 237 | + { |
| 238 | + using value_type = T; |
| 239 | + using size = std::integral_constant<std::size_t, N>; |
| 240 | + }; |
| 241 | + |
| 242 | + template<typename T> inline constexpr auto is_static_container_v = is_static_container<T>::value; |
| 243 | + |
| 244 | + //================================================================================================ |
| 245 | + //! @ingroup traits |
| 246 | + //! @brief Returns the number of elements of a kumi::static_container |
| 247 | + //! |
| 248 | + //! @tparam T kumi::static_container to inspect |
| 249 | + //! |
| 250 | + //! ## Helper value |
| 251 | + //! @code |
| 252 | + //! template<typename T> inline constexpr auto container_size_v = container_size<T>::value; |
| 253 | + //! @endcode |
| 254 | + //================================================================================================ |
| 255 | + template<typename T> struct container_size : is_static_container<T>::size |
| 256 | + { |
| 257 | + }; |
| 258 | + |
| 259 | + template<typename T> struct container_size<T&> : container_size<T> |
| 260 | + { |
| 261 | + }; |
| 262 | + |
| 263 | + template<typename T> struct container_size<T&&> : container_size<T> |
| 264 | + { |
| 265 | + }; |
| 266 | + |
| 267 | + template<typename T> struct container_size<T const&> : container_size<T> |
| 268 | + { |
| 269 | + }; |
| 270 | + |
| 271 | + template<typename T> struct container_size<T const&&> : container_size<T> |
| 272 | + { |
| 273 | + }; |
| 274 | + |
| 275 | + template<typename T> inline constexpr auto container_size_v = container_size<T>::value; |
| 276 | + |
| 277 | + //================================================================================================ |
| 278 | + //! @ingroup traits |
| 279 | + //! @brief Provides access to the type of the elements of a kumi::static_container. |
| 280 | + //! |
| 281 | + //! @tparam T kumi::static_container to access |
| 282 | + //! |
| 283 | + //! ## Helper type |
| 284 | + //! @code |
| 285 | + //! namespace kumi |
| 286 | + //! { |
| 287 | + //! template<typename T> using container_type_t = typename container_type<T>::type; |
| 288 | + //! } |
| 289 | + //! @endcode |
| 290 | + //================================================================================================ |
| 291 | + template<typename T> struct container_type : is_static_container<T>::value_type |
| 292 | + { |
| 293 | + }; |
| 294 | + |
| 295 | + template<typename T> struct container_type<T&> : container_type<T> |
| 296 | + { |
| 297 | + }; |
| 298 | + |
| 299 | + template<typename T> struct container_type<T&&> : container_type<T> |
| 300 | + { |
| 301 | + }; |
| 302 | + |
| 303 | + template<typename T> struct container_type<T const&> : container_type<T> |
| 304 | + { |
| 305 | + }; |
| 306 | + |
| 307 | + template<typename T> struct container_type<T const&&> : container_type<T> |
| 308 | + { |
| 309 | + }; |
| 310 | + |
| 311 | + template<typename T> using container_type_t = typename container_type<T>::type; |
| 312 | +} |
| 313 | + |
180 | 314 | namespace kumi |
181 | 315 | { |
182 | 316 | //================================================================================================ |
@@ -404,4 +538,10 @@ namespace kumi |
404 | 538 | // Forward declaration |
405 | 539 | template<typename... Ts> struct tuple; |
406 | 540 | template<typename... Ts> struct record; |
| 541 | + |
| 542 | + template<typename T> |
| 543 | + requires(is_static_container_v<T> && (_::non_empty_tuple<T> || _::empty_tuple<T>)) |
| 544 | + struct is_product_type<T> : std::true_type |
| 545 | + { |
| 546 | + }; |
407 | 547 | } |
0 commit comments