diff options
Diffstat (limited to 'boost/hof/construct.hpp')
-rw-r--r-- | boost/hof/construct.hpp | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/boost/hof/construct.hpp b/boost/hof/construct.hpp new file mode 100644 index 0000000000..daf9eca42f --- /dev/null +++ b/boost/hof/construct.hpp @@ -0,0 +1,302 @@ +/*============================================================================= + Copyright (c) 2015 Paul Fultz II + construct.h + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#ifndef BOOST_HOF_GUARD_CONSTRUCT_H +#define BOOST_HOF_GUARD_CONSTRUCT_H + +/// construct +/// ========= +/// +/// Description +/// ----------- +/// +/// The `construct` function returns a function object that will construct the +/// object when the called. A template can also be given, which it will deduce +/// the parameters to the template. The `construct_meta` can be used to +/// construct the object from a metafunction. +/// +/// Synopsis +/// -------- +/// +/// // Construct by decaying each value +/// template<class T> +/// constexpr auto construct(); +/// +/// template<template<class...> class Template> +/// constexpr auto construct(); +/// +/// // Construct by deducing lvalues by reference and rvalue reference by reference +/// template<class T> +/// constexpr auto construct_forward(); +/// +/// template<template<class...> class Template> +/// constexpr auto construct_forward(); +/// +/// // Construct by deducing lvalues by reference and rvalues by value. +/// template<class T> +/// constexpr auto construct_basic(); +/// +/// template<template<class...> class Template> +/// constexpr auto construct_basic(); +/// +/// // Construct by deducing the object from a metafunction +/// template<class MetafunctionClass> +/// constexpr auto construct_meta(); +/// +/// template<template<class...> class MetafunctionTemplate> +/// constexpr auto construct_meta(); +/// +/// Semantics +/// --------- +/// +/// assert(construct<T>()(xs...) == T(xs...)); +/// assert(construct<Template>()(xs...) == Template<decltype(xs)...>(xs...)); +/// assert(construct_meta<MetafunctionClass>()(xs...) == MetafunctionClass::apply<decltype(xs)...>(xs...)); +/// assert(construct_meta<MetafunctionTemplate>()(xs...) == MetafunctionTemplate<decltype(xs)...>::type(xs...)); +/// +/// Requirements +/// ------------ +/// +/// MetafunctionClass must be a: +/// +/// * [MetafunctionClass](MetafunctionClass) +/// +/// MetafunctionTemplate<Ts...> must be a: +/// +/// * [Metafunction](Metafunction) +/// +/// T, Template<Ts..>, MetafunctionClass::apply<Ts...>, and +/// MetafunctionTemplate<Ts...>::type must be: +/// +/// * MoveConstructible +/// +/// Example +/// ------- +/// +/// #include <boost/hof.hpp> +/// #include <cassert> +/// #include <vector> +/// +/// int main() { +/// auto v = boost::hof::construct<std::vector<int>>()(5, 5); +/// assert(v.size() == 5); +/// } +/// + +#include <boost/hof/detail/forward.hpp> +#include <boost/hof/detail/move.hpp> +#include <boost/hof/detail/delegate.hpp> +#include <boost/hof/detail/join.hpp> +#include <boost/hof/detail/remove_rvalue_reference.hpp> +#include <boost/hof/decay.hpp> + +#include <initializer_list> + +namespace boost { namespace hof { + +namespace detail { + +template<class T, class=void> +struct construct_f +{ + typedef typename std::aligned_storage<sizeof(T)>::type storage; + + struct storage_holder + { + storage * s; + storage_holder(storage* x) noexcept : s(x) + {} + + T& data() noexcept + { + return *reinterpret_cast<T*>(s); + } + + ~storage_holder() noexcept(noexcept(std::declval<T>().~T())) + { + this->data().~T(); + } + }; + + constexpr construct_f() noexcept + {} + template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)> + T operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, Ts&&...) + { + storage buffer{}; + new(&buffer) T(BOOST_HOF_FORWARD(Ts)(xs)...); + storage_holder h(&buffer); + return boost::hof::move(h.data()); + } + + template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)> + T operator()(std::initializer_list<X>&& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&&) + { + storage buffer{}; + new(&buffer) T(static_cast<std::initializer_list<X>&&>(x)); + storage_holder h(&buffer); + return h.data(); + } + + template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)> + T operator()(std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, std::initializer_list<X>&) + { + storage buffer{}; + new(&buffer) T(x); + storage_holder h(&buffer); + return h.data(); + } + + template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)> + T operator()(const std::initializer_list<X>& x) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, const std::initializer_list<X>&) + { + storage buffer{}; + new(&buffer) T(x); + storage_holder h(&buffer); + return h.data(); + } +}; + +template<class T> +struct construct_f<T, typename std::enable_if<BOOST_HOF_IS_LITERAL(T)>::type> +{ + constexpr construct_f() noexcept + {} + template<class... Ts, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)> + constexpr T operator()(Ts&&... xs) const noexcept + { + return T(BOOST_HOF_FORWARD(Ts)(xs)...); + } + + template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)> + constexpr T operator()(std::initializer_list<X>&& x) const noexcept + { + return T(static_cast<std::initializer_list<X>&&>(x)); + } + + template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)> + constexpr T operator()(std::initializer_list<X>& x) const noexcept + { + return T(x); + } + + template<class X, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)> + constexpr T operator()(const std::initializer_list<X>& x) const noexcept + { + return T(x); + } +}; + +template<template<class...> class Template, template<class...> class D> +struct construct_template_f +{ + constexpr construct_template_f() noexcept + {} + template<class... Ts, class Result=BOOST_HOF_JOIN(Template, typename D<Ts>::type...), + BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)> + constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...) + { + return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...); + } +}; + +template<class MetafunctionClass> +struct construct_meta_f +{ + constexpr construct_meta_f() noexcept + {} + + template<class... Ts> + struct apply + : MetafunctionClass::template apply<Ts...> + {}; + + template<class... Ts, + class Metafunction=BOOST_HOF_JOIN(apply, Ts...), + class Result=typename Metafunction::type, + BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)> + constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...) + { + return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...); + } +}; + +template<template<class...> class MetafunctionTemplate> +struct construct_meta_template_f +{ + constexpr construct_meta_template_f() noexcept + {} + template<class... Ts, + class Metafunction=BOOST_HOF_JOIN(MetafunctionTemplate, Ts...), + class Result=typename Metafunction::type, + BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)> + constexpr Result operator()(Ts&&... xs) const BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Result, Ts&&...) + { + return construct_f<Result>()(BOOST_HOF_FORWARD(Ts)(xs)...); + } +}; + + +template<class T> +struct construct_id +{ + typedef T type; +}; + +} + +template<class T> +constexpr detail::construct_f<T> construct() noexcept +{ + return {}; +} +// These overloads are provide for consistency +template<class T> +constexpr detail::construct_f<T> construct_forward() noexcept +{ + return {}; +} + +template<class T> +constexpr detail::construct_f<T> construct_basic() noexcept +{ + return {}; +} + +template<template<class...> class Template> +constexpr detail::construct_template_f<Template, detail::decay_mf> construct() noexcept +{ + return {}; +} + +template<template<class...> class Template> +constexpr detail::construct_template_f<Template, detail::construct_id> construct_forward() noexcept +{ + return {}; +} + +template<template<class...> class Template> +constexpr detail::construct_template_f<Template, detail::remove_rvalue_reference> construct_basic() noexcept +{ + return {}; +} + +template<class T> +constexpr detail::construct_meta_f<T> construct_meta() noexcept +{ + return {}; +} + +template<template<class...> class Template> +constexpr detail::construct_meta_template_f<Template> construct_meta() noexcept +{ + return {}; +} + +}} // namespace boost::hof + +#endif |