Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:15

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     construct.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_CONSTRUCT_H
0009 #define BOOST_HOF_GUARD_CONSTRUCT_H
0010 
0011 /// construct
0012 /// =========
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `construct` function returns a function object that will construct the
0018 /// object when the called. A template can also be given, which it will deduce
0019 /// the parameters to the template. The `construct_meta` can be used to
0020 /// construct the object from a metafunction.
0021 /// 
0022 /// Synopsis
0023 /// --------
0024 /// 
0025 ///     // Construct by decaying each value
0026 ///     template<class T>
0027 ///     constexpr auto construct();
0028 /// 
0029 ///     template<template<class...> class Template>
0030 ///     constexpr auto construct();
0031 /// 
0032 ///     // Construct by deducing lvalues by reference and rvalue reference by reference
0033 ///     template<class T>
0034 ///     constexpr auto construct_forward();
0035 /// 
0036 ///     template<template<class...> class Template>
0037 ///     constexpr auto construct_forward();
0038 /// 
0039 ///     // Construct by deducing lvalues by reference and rvalues by value.
0040 ///     template<class T>
0041 ///     constexpr auto construct_basic();
0042 /// 
0043 ///     template<template<class...> class Template>
0044 ///     constexpr auto construct_basic();
0045 /// 
0046 ///     // Construct by deducing the object from a metafunction
0047 ///     template<class MetafunctionClass>
0048 ///     constexpr auto construct_meta();
0049 /// 
0050 ///     template<template<class...> class MetafunctionTemplate>
0051 ///     constexpr auto construct_meta();
0052 /// 
0053 /// Semantics
0054 /// ---------
0055 /// 
0056 ///     assert(construct<T>()(xs...) == T(xs...));
0057 ///     assert(construct<Template>()(xs...) == Template<decltype(xs)...>(xs...));
0058 ///     assert(construct_meta<MetafunctionClass>()(xs...) == MetafunctionClass::apply<decltype(xs)...>(xs...));
0059 ///     assert(construct_meta<MetafunctionTemplate>()(xs...) == MetafunctionTemplate<decltype(xs)...>::type(xs...));
0060 /// 
0061 /// Requirements
0062 /// ------------
0063 /// 
0064 /// MetafunctionClass must be a:
0065 /// 
0066 /// * [MetafunctionClass](MetafunctionClass)
0067 /// 
0068 /// MetafunctionTemplate<Ts...> must be a:
0069 /// 
0070 /// * [Metafunction](Metafunction)
0071 /// 
0072 /// T, Template<Ts..>, MetafunctionClass::apply<Ts...>, and
0073 /// MetafunctionTemplate<Ts...>::type must be:
0074 /// 
0075 /// * MoveConstructible
0076 /// 
0077 /// Example
0078 /// -------
0079 /// 
0080 ///     #include <boost/hof.hpp>
0081 ///     #include <cassert>
0082 ///     #include <vector>
0083 /// 
0084 ///     int main() {
0085 ///         auto v = boost::hof::construct<std::vector<int>>()(5, 5);
0086 ///         assert(v.size() == 5);
0087 ///     }
0088 /// 
0089 
0090 #include <boost/hof/detail/forward.hpp>
0091 #include <boost/hof/detail/move.hpp>
0092 #include <boost/hof/detail/delegate.hpp>
0093 #include <boost/hof/detail/join.hpp>
0094 #include <boost/hof/detail/remove_rvalue_reference.hpp>
0095 #include <boost/hof/decay.hpp>
0096 
0097 #include <initializer_list>
0098 
0099 namespace boost { namespace hof { 
0100 
0101 namespace detail {
0102 
0103 template<class T, class=void>
0104 struct construct_f
0105 {
0106     typedef typename std::aligned_storage<sizeof(T)>::type storage;
0107 
0108     struct storage_holder
0109     {
0110         storage * s;
0111         storage_holder(storage* x) noexcept : s(x)
0112         {}
0113 
0114         T& data() noexcept
0115         {
0116             return *reinterpret_cast<T*>(s);
0117         }
0118 
0119         ~storage_holder() noexcept(noexcept(std::declval<T>().~T()))
0120         {
0121             this->data().~T();
0122         }
0123     };
0124 
0125     constexpr construct_f() noexcept
0126     {}
0127     template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
0128     T operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, Ts&&...)
0129     {
0130         storage buffer{};
0131         new(&buffer) T(BOOST_HOF_FORWARD(Ts)(xs)...);
0132         storage_holder h(&buffer);
0133         return boost::hof::move(h.data());
0134     }
0135 
0136     template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
0137     T operator()(std::initializer_list<X>&& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&&)
0138     {
0139         storage buffer{};
0140         new(&buffer) T(static_cast<std::initializer_list<X>&&>(x));
0141         storage_holder h(&buffer);
0142         return h.data();
0143     }
0144 
0145     template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
0146     T operator()(std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&)
0147     {
0148         storage buffer{};
0149         new(&buffer) T(x);
0150         storage_holder h(&buffer);
0151         return h.data();
0152     }
0153 
0154     template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
0155     T operator()(const std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, const std::initializer_list<X>&)
0156     {
0157         storage buffer{};
0158         new(&buffer) T(x);
0159         storage_holder h(&buffer);
0160         return h.data();
0161     }
0162 };
0163 
0164 template<class T>
0165 struct construct_f<T, typename std::enable_if<BOOST_HOF_IS_LITERAL(T)>::type>
0166 {
0167     constexpr construct_f() noexcept
0168     {}
0169     template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
0170     constexpr T operator()(Ts&&... xs) const noexcept
0171     {
0172         return T(BOOST_HOF_FORWARD(Ts)(xs)...);
0173     }
0174 
0175     template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
0176     constexpr T operator()(std::initializer_list<X>&& x) const noexcept
0177     {
0178         return T(static_cast<std::initializer_list<X>&&>(x));
0179     }
0180 
0181     template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
0182     constexpr T operator()(std::initializer_list<X>& x) const noexcept
0183     {
0184         return T(x);
0185     }
0186 
0187     template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
0188     constexpr T operator()(const std::initializer_list<X>& x) const noexcept
0189     {
0190         return T(x);
0191     }
0192 };
0193 
0194 template<template<class...> class Template, template<class...> class D>
0195 struct construct_template_f
0196 {
0197     constexpr construct_template_f() noexcept
0198     {}
0199     template<class... Ts, class Result=BOOST_HOF_JOIN(Template, typename D<Ts>::type...), 
0200         BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
0201     constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
0202     {
0203         return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
0204     }
0205 };
0206 
0207 template<class MetafunctionClass>
0208 struct construct_meta_f
0209 {
0210     constexpr construct_meta_f() noexcept
0211     {}
0212 
0213     template<class... Ts>
0214     struct apply
0215     : MetafunctionClass::template apply<Ts...>
0216     {};
0217 
0218     template<class... Ts, 
0219         class Metafunction=BOOST_HOF_JOIN(apply, Ts...), 
0220         class Result=typename Metafunction::type, 
0221         BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
0222     constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
0223     {
0224         return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
0225     }
0226 };
0227 
0228 template<template<class...> class MetafunctionTemplate>
0229 struct construct_meta_template_f
0230 {
0231     constexpr construct_meta_template_f() noexcept
0232     {}
0233     template<class... Ts, 
0234         class Metafunction=BOOST_HOF_JOIN(MetafunctionTemplate, Ts...), 
0235         class Result=typename Metafunction::type, 
0236         BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
0237     constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...)
0238     {
0239         return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...);
0240     }
0241 };
0242 
0243 
0244 template<class T>
0245 struct construct_id
0246 {
0247     typedef T type;
0248 };
0249 
0250 }
0251 
0252 template<class T>
0253 constexpr detail::construct_f<T> construct() noexcept
0254 {
0255     return {};
0256 }
0257 // These overloads are provide for consistency
0258 template<class T>
0259 constexpr detail::construct_f<T> construct_forward() noexcept
0260 {
0261     return {};
0262 }
0263 
0264 template<class T>
0265 constexpr detail::construct_f<T> construct_basic() noexcept
0266 {
0267     return {};
0268 }
0269 
0270 template<template<class...> class Template>
0271 constexpr detail::construct_template_f<Template, detail::decay_mf> construct() noexcept
0272 {
0273     return {};
0274 }
0275 
0276 template<template<class...> class Template>
0277 constexpr detail::construct_template_f<Template, detail::construct_id> construct_forward() noexcept
0278 {
0279     return {};
0280 }
0281 
0282 template<template<class...> class Template>
0283 constexpr detail::construct_template_f<Template, detail::remove_rvalue_reference> construct_basic() noexcept
0284 {
0285     return {};
0286 }
0287 
0288 template<class T>
0289 constexpr detail::construct_meta_f<T> construct_meta() noexcept
0290 {
0291     return {};
0292 }
0293 
0294 template<template<class...> class Template>
0295 constexpr detail::construct_meta_template_f<Template> construct_meta() noexcept
0296 {
0297     return {};
0298 }
0299 
0300 }} // namespace boost::hof
0301 
0302 #endif