• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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