construct.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*=============================================================================
  2. Copyright (c) 2015 Paul Fultz II
  3. construct.h
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #ifndef BOOST_HOF_GUARD_CONSTRUCT_H
  8. #define BOOST_HOF_GUARD_CONSTRUCT_H
  9. /// construct
  10. /// =========
  11. ///
  12. /// Description
  13. /// -----------
  14. ///
  15. /// The `construct` function returns a function object that will construct the
  16. /// object when the called. A template can also be given, which it will deduce
  17. /// the parameters to the template. The `construct_meta` can be used to
  18. /// construct the object from a metafunction.
  19. ///
  20. /// Synopsis
  21. /// --------
  22. ///
  23. /// // Construct by decaying each value
  24. /// template<class T>
  25. /// constexpr auto construct();
  26. ///
  27. /// template<template<class...> class Template>
  28. /// constexpr auto construct();
  29. ///
  30. /// // Construct by deducing lvalues by reference and rvalue reference by reference
  31. /// template<class T>
  32. /// constexpr auto construct_forward();
  33. ///
  34. /// template<template<class...> class Template>
  35. /// constexpr auto construct_forward();
  36. ///
  37. /// // Construct by deducing lvalues by reference and rvalues by value.
  38. /// template<class T>
  39. /// constexpr auto construct_basic();
  40. ///
  41. /// template<template<class...> class Template>
  42. /// constexpr auto construct_basic();
  43. ///
  44. /// // Construct by deducing the object from a metafunction
  45. /// template<class MetafunctionClass>
  46. /// constexpr auto construct_meta();
  47. ///
  48. /// template<template<class...> class MetafunctionTemplate>
  49. /// constexpr auto construct_meta();
  50. ///
  51. /// Semantics
  52. /// ---------
  53. ///
  54. /// assert(construct<T>()(xs...) == T(xs...));
  55. /// assert(construct<Template>()(xs...) == Template<decltype(xs)...>(xs...));
  56. /// assert(construct_meta<MetafunctionClass>()(xs...) == MetafunctionClass::apply<decltype(xs)...>(xs...));
  57. /// assert(construct_meta<MetafunctionTemplate>()(xs...) == MetafunctionTemplate<decltype(xs)...>::type(xs...));
  58. ///
  59. /// Requirements
  60. /// ------------
  61. ///
  62. /// MetafunctionClass must be a:
  63. ///
  64. /// * [MetafunctionClass](MetafunctionClass)
  65. ///
  66. /// MetafunctionTemplate<Ts...> must be a:
  67. ///
  68. /// * [Metafunction](Metafunction)
  69. ///
  70. /// T, Template<Ts..>, MetafunctionClass::apply<Ts...>, and
  71. /// MetafunctionTemplate<Ts...>::type must be:
  72. ///
  73. /// * MoveConstructible
  74. ///
  75. /// Example
  76. /// -------
  77. ///
  78. /// #include <boost/hof.hpp>
  79. /// #include <cassert>
  80. /// #include <vector>
  81. ///
  82. /// int main() {
  83. /// auto v = boost::hof::construct<std::vector<int>>()(5, 5);
  84. /// assert(v.size() == 5);
  85. /// }
  86. ///
  87. #include <boost/hof/detail/forward.hpp>
  88. #include <boost/hof/detail/move.hpp>
  89. #include <boost/hof/detail/delegate.hpp>
  90. #include <boost/hof/detail/join.hpp>
  91. #include <boost/hof/detail/remove_rvalue_reference.hpp>
  92. #include <boost/hof/decay.hpp>
  93. #include <initializer_list>
  94. namespace boost { namespace hof {
  95. namespace detail {
  96. template<class T, class=void>
  97. struct construct_f
  98. {
  99. typedef typename std::aligned_storage<sizeof(T)>::type storage;
  100. struct storage_holder
  101. {
  102. storage * s;
  103. storage_holder(storage* x) noexcept : s(x)
  104. {}
  105. T& data() noexcept
  106. {
  107. return *reinterpret_cast<T*>(s);
  108. }
  109. ~storage_holder() noexcept(noexcept(std::declval<T>().~T()))
  110. {
  111. this->data().~T();
  112. }
  113. };
  114. constexpr construct_f() noexcept
  115. {}
  116. template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
  117. T operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, Ts&&...)
  118. {
  119. storage buffer{};
  120. new(&buffer) T(BOOST_HOF_FORWARD(Ts)(xs)...);
  121. storage_holder h(&buffer);
  122. return boost::hof::move(h.data());
  123. }
  124. template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
  125. T operator()(std::initializer_list<X>&& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&&)
  126. {
  127. storage buffer{};
  128. new(&buffer) T(static_cast<std::initializer_list<X>&&>(x));
  129. storage_holder h(&buffer);
  130. return h.data();
  131. }
  132. template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
  133. T operator()(std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&)
  134. {
  135. storage buffer{};
  136. new(&buffer) T(x);
  137. storage_holder h(&buffer);
  138. return h.data();
  139. }
  140. template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
  141. T operator()(const std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, const std::initializer_list<X>&)
  142. {
  143. storage buffer{};
  144. new(&buffer) T(x);
  145. storage_holder h(&buffer);
  146. return h.data();
  147. }
  148. };
  149. template<class T>
  150. struct construct_f<T, typename std::enable_if<BOOST_HOF_IS_LITERAL(T)>::type>
  151. {
  152. constexpr construct_f() noexcept
  153. {}
  154. template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
  155. constexpr T operator()(Ts&&... xs) const noexcept
  156. {
  157. return T(BOOST_HOF_FORWARD(Ts)(xs)...);
  158. }
  159. template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
  160. constexpr T operator()(std::initializer_list<X>&& x) const noexcept
  161. {
  162. return T(static_cast<std::initializer_list<X>&&>(x));
  163. }
  164. template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
  165. constexpr T operator()(std::initializer_list<X>& x) const noexcept
  166. {
  167. return T(x);
  168. }
  169. template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
  170. constexpr T operator()(const std::initializer_list<X>& x) const noexcept
  171. {
  172. return T(x);
  173. }
  174. };
  175. template<template<class...> class Template, template<class...> class D>
  176. struct construct_template_f
  177. {
  178. constexpr construct_template_f() noexcept
  179. {}
  180. template<class... Ts, class Result=BOOST_HOF_JOIN(Template, typename D<Ts>::type...),
  181. BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
  182. constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
  183. {
  184. return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
  185. }
  186. };
  187. template<class MetafunctionClass>
  188. struct construct_meta_f
  189. {
  190. constexpr construct_meta_f() noexcept
  191. {}
  192. template<class... Ts>
  193. struct apply
  194. : MetafunctionClass::template apply<Ts...>
  195. {};
  196. template<class... Ts,
  197. class Metafunction=BOOST_HOF_JOIN(apply, Ts...),
  198. class Result=typename Metafunction::type,
  199. BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
  200. constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
  201. {
  202. return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
  203. }
  204. };
  205. template<template<class...> class MetafunctionTemplate>
  206. struct construct_meta_template_f
  207. {
  208. constexpr construct_meta_template_f() noexcept
  209. {}
  210. template<class... Ts,
  211. class Metafunction=BOOST_HOF_JOIN(MetafunctionTemplate, Ts...),
  212. class Result=typename Metafunction::type,
  213. BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
  214. constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
  215. {
  216. return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
  217. }
  218. };
  219. template<class T>
  220. struct construct_id
  221. {
  222. typedef T type;
  223. };
  224. }
  225. template<class T>
  226. constexpr detail::construct_f<T> construct() noexcept
  227. {
  228. return {};
  229. }
  230. // These overloads are provide for consistency
  231. template<class T>
  232. constexpr detail::construct_f<T> construct_forward() noexcept
  233. {
  234. return {};
  235. }
  236. template<class T>
  237. constexpr detail::construct_f<T> construct_basic() noexcept
  238. {
  239. return {};
  240. }
  241. template<template<class...> class Template>
  242. constexpr detail::construct_template_f<Template, detail::decay_mf> construct() noexcept
  243. {
  244. return {};
  245. }
  246. template<template<class...> class Template>
  247. constexpr detail::construct_template_f<Template, detail::construct_id> construct_forward() noexcept
  248. {
  249. return {};
  250. }
  251. template<template<class...> class Template>
  252. constexpr detail::construct_template_f<Template, detail::remove_rvalue_reference> construct_basic() noexcept
  253. {
  254. return {};
  255. }
  256. template<class T>
  257. constexpr detail::construct_meta_f<T> construct_meta() noexcept
  258. {
  259. return {};
  260. }
  261. template<template<class...> class Template>
  262. constexpr detail::construct_meta_template_f<Template> construct_meta() noexcept
  263. {
  264. return {};
  265. }
  266. }} // namespace boost::hof
  267. #endif