Advertisement
Guest User

Untitled

a guest
Mar 24th, 2019
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.33 KB | None | 0 0
  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 */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement