選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

176 行
6.1 KiB

  1. #pragma once
  2. #include <cpputils/mp/misc/when.h>
  3. #include <cpputils/mp/misc/tag_of.h>
  4. #include <cpputils/mp/core/conditionals.h>
  5. namespace utl {
  6. namespace mp {
  7. namespace __impl /* forward declaration */
  8. {
  9. template<typename To>
  10. struct to_t;
  11. template <typename From, typename To, typename = void>
  12. struct is_mp_convertible_impl;
  13. template <typename From, typename To, typename = void>
  14. struct is_embedded_impl;
  15. }
  16. template<typename To>
  17. constexpr __impl::to_t<To> to { };
  18. template <typename From, typename To>
  19. using is_mp_convertible = __impl::is_mp_convertible_impl<From, To>;
  20. template <typename From, typename To>
  21. using is_embedded = __impl::is_embedded_impl<From, To>;
  22. namespace __impl /* implementation */
  23. {
  24. struct no_conversion { };
  25. template <bool = true>
  26. struct embedding { };
  27. /* to_impl */
  28. template <typename To, typename From, typename = void>
  29. struct to_impl;
  30. template <typename To, typename From, typename>
  31. struct to_impl :
  32. public to_impl<To, From, when<true>>
  33. { };
  34. template <typename To, typename From, bool condition>
  35. struct to_impl<To, From, when<condition>> :
  36. public no_conversion
  37. {
  38. template <typename X>
  39. static constexpr auto apply(const X&)
  40. { static_assert(wrong<to_impl<To, From>, X> { }, "no conversion is available between the provided types"); }
  41. };
  42. template <typename To, typename From>
  43. struct to_impl<To, From, when_valid<decltype(static_cast<To>(std::declval<From>()))>>
  44. {
  45. template <typename X>
  46. static constexpr To apply(X&& x)
  47. { return static_cast<To>(std::forward<X>(x)); }
  48. };
  49. template <typename To>
  50. struct to_impl<To, To> :
  51. public embedding<>
  52. {
  53. template <typename X>
  54. static constexpr X apply(X&& x)
  55. { return std::forward<X&&>(x); }
  56. };
  57. template <typename T>
  58. struct to_impl<T*, decltype(nullptr)> :
  59. public embedding<>
  60. {
  61. static constexpr T* apply(decltype(nullptr))
  62. { return nullptr; }
  63. };
  64. /* to_t */
  65. template <typename To>
  66. struct to_t
  67. {
  68. template <typename X>
  69. constexpr auto operator()(X&& x) const
  70. {
  71. using From = tag_of<X>;
  72. return to_impl<To, From>::apply(std::forward<X>(x));
  73. }
  74. };
  75. #define DEFINE_EMBEDDING_IMPL(TO, FROM) \
  76. template <> \
  77. struct to_impl<TO, FROM> : \
  78. public embedding<> \
  79. { \
  80. static constexpr TO apply(FROM x) \
  81. { return static_cast<TO>(x); } \
  82. }
  83. DEFINE_EMBEDDING_IMPL(long double, double);
  84. DEFINE_EMBEDDING_IMPL(long double, float);
  85. DEFINE_EMBEDDING_IMPL(double , float);
  86. DEFINE_EMBEDDING_IMPL(signed long long, signed long);
  87. DEFINE_EMBEDDING_IMPL(signed long long, signed int);
  88. DEFINE_EMBEDDING_IMPL(signed long long, signed short);
  89. DEFINE_EMBEDDING_IMPL(signed long long, signed char);
  90. DEFINE_EMBEDDING_IMPL(signed long , signed int);
  91. DEFINE_EMBEDDING_IMPL(signed long , signed short);
  92. DEFINE_EMBEDDING_IMPL(signed long , signed char);
  93. DEFINE_EMBEDDING_IMPL(signed int , signed short);
  94. DEFINE_EMBEDDING_IMPL(signed int , signed char);
  95. DEFINE_EMBEDDING_IMPL(signed short , signed char);
  96. DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long);
  97. DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int);
  98. DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short);
  99. DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char);
  100. DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int);
  101. DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short);
  102. DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char);
  103. DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short);
  104. DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char);
  105. DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char);
  106. #undef DEFINE_EMBEDDING_IMPL
  107. template<class T>
  108. using copy_char_signedness = if_t<
  109. std::is_signed<char>,
  110. typename std::make_signed<T>::type,
  111. typename std::make_unsigned<T>::type>;
  112. #define DEFINE_CHAR_EMBEDDING_IMPL(TO) \
  113. template <> \
  114. struct to_impl<copy_char_signedness<TO>, char> \
  115. : public embedding<> \
  116. { \
  117. static constexpr copy_char_signedness<TO> apply(char x) \
  118. { return static_cast<TO>(x); } \
  119. }
  120. DEFINE_CHAR_EMBEDDING_IMPL(long long);
  121. DEFINE_CHAR_EMBEDDING_IMPL(long);
  122. DEFINE_CHAR_EMBEDDING_IMPL(int);
  123. DEFINE_CHAR_EMBEDDING_IMPL(short);
  124. #undef DEFINE_CHAR_EMBEDDING_IMPL
  125. /* is_mp_convertible_impl */
  126. template <typename From, typename To, typename>
  127. struct is_mp_convertible_impl :
  128. public std::true_type
  129. { };
  130. template <typename From, typename To>
  131. struct is_mp_convertible_impl<From, To, decltype((void) static_cast<no_conversion>(std::declval<to_impl<To, From>>()))> :
  132. public std::false_type
  133. { };
  134. /* is_embedded_impl */
  135. template <typename From, typename To, typename>
  136. struct is_embedded_impl :
  137. public std::false_type
  138. { };
  139. template <typename From, typename To>
  140. struct is_embedded_impl<From, To, decltype((void) static_cast<embedding<true>>(std::declval<to_impl<To, From>>()))> :
  141. public std::true_type
  142. { };
  143. }
  144. }
  145. }