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