SHARE
TWEET

Untitled

a guest Mar 24th, 2019 54 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * yk_essentials.hpp
  3.  *
  4.  * @author Peter Lenkefi
  5.  * @date 2019-03-19
  6.  * @description Things that make coding in C++ cleaner/easier.
  7.  */
  8.  
  9. #ifndef YK_ESSENTIALS_HPP
  10. #define YK_ESSENTIALS_HPP
  11.  
  12. #include <cstddef>
  13. #include <type_traits>
  14. #include "yk_preproc.hpp"
  15.  
  16. /**
  17.  * First we assert the language.
  18.  */
  19. #if yk_pp_lang != yk_pp_cpp
  20. #   error "The essentials header may only be used with a C++ compiler!"
  21. #endif
  22.  
  23. /**
  24.  * At least C++11.
  25.  */
  26. #if yk_pp_standard < yk_pp_11
  27. #   error "The essentials header requires a C++11 compiler or newer!"
  28. #endif
  29.  
  30. /**
  31.  * Based on standard version.
  32.  */
  33. #if yk_pp_standard >= yk_pp_14
  34. #   define yk_constexpr_14 constexpr
  35. #else
  36. #   define yk_constexpr_14
  37. #endif
  38.  
  39. namespace yk {
  40.  
  41. /**
  42.  * Simplifies concept checking with a nicer message.
  43.  *
  44.  * Example usage:
  45.  * template <typename Range>
  46.  * struct foo {
  47.  *     yk_assert_concept(is_range_v<Range>);
  48.  * };
  49.  *
  50.  * If the assertion fails, the error message is:
  51.  * "Concept assertion is_range_v<Range> failed!"
  52.  */
  53. #define yk_assert_concept(...) \
  54. static_assert(__VA_ARGS__, "Concept assertion " #__VA_ARGS__ " failed!")
  55.  
  56. /**
  57.  * Constrains a function to a condition.
  58.  *
  59.  * Example usage:
  60.  * template <std::size_t N>
  61.  * struct vec {
  62.  *     yk_requires(N == 3)
  63.  *     auto cross(vec const& o) { ... }
  64.  * };
  65.  */
  66. #define yk_requires(...) \
  67. template <yk_requires_t(__VA_ARGS__)>
  68.  
  69. /**
  70.  * Constraints a function to a condition in a template.
  71.  *
  72.  * Example usage:
  73.  * template <typename R, yk_requires_t(is_range_v<R>)>
  74.  * void for_each(R&& r) { ... }
  75.  */
  76. #define yk_requires_t(...) \
  77. yk_prelude_requires_t1(yk_pp_unique_id(concept_req), __VA_ARGS__)
  78.  
  79. #define yk_prelude_requires_t1(id, ...)                             \
  80. bool id = false,                                                    \
  81. ::std::enable_if_t<id || (__VA_ARGS__), ::std::nullptr_t> = nullptr
  82.  
  83. /**
  84.  * A macro to create a new tag-type.
  85.  */
  86. namespace detail {
  87.  
  88. template <typename>
  89. struct tag_type {};
  90.  
  91. } /* namespace detail */
  92.  
  93. #define yk_create_tag_type() \
  94. ::yk::detail::tag_type<struct yk_pp_unique_id(tag_type_param)>
  95.  
  96. /**
  97.  * A macro that helps forwarding in the trivial case.
  98.  *
  99.  * Example usage:
  100.  * template <typename TFwd>
  101.  * void foo(T&& arg) {
  102.  *     bar(yk_fwd(arg));
  103.  * }
  104.  */
  105. #define yk_fwd(...) \
  106. ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
  107.  
  108. /**
  109.  * Utility for CRTP-based code.
  110.  * Removes the need for casting to underlying type with the provided self()
  111.  * member functions. It's important to call them with this->self() to avoid
  112.  * name resolving errors.
  113.  *
  114.  * It can be used to inject extra functionality (like metaclasses). See the
  115.  * example below.
  116.  *
  117.  * Example usage:
  118.  * template <typename Self>
  119.  * class foo_base : public crtp<Self> {
  120.  * public:
  121.  *     int bar() {
  122.  *        return this->self().baz() * 2;
  123.  *     }
  124.  * };
  125.  *
  126.  * class foo : public foo_base<foo> {
  127.  * public:
  128.  *     int baz() { return 1; }
  129.  * };
  130.  *
  131.  * // foo has a function called bar() too
  132.  */
  133. using crtp_default_tag = yk_create_tag_type();
  134.  
  135. template <typename Self, typename Tag = crtp_default_tag>
  136. class crtp {
  137. public:
  138.     using self_type = Self;
  139.  
  140.     [[nodiscard]]
  141.     yk_constexpr_14 self_type& self() noexcept {
  142.         return static_cast<self_type&>(*this);
  143.     }
  144.  
  145.     [[nodiscard]]
  146.     yk_constexpr_14 self_type const& self() const noexcept {
  147.         return static_cast<self_type const&>(*this);
  148.     }
  149. };
  150.  
  151. } /* namespace yk */
  152.  
  153. #undef yk_constexpr_14
  154.  
  155. #endif /* YK_ESSENTIALS_HPP */
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top