/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTL_SEQUENCE_HPP #define XTL_SEQUENCE_HPP #include #include #include #include #include #include "xtl_config.hpp" #include "xmeta_utils.hpp" namespace xtl { template S make_sequence(typename S::size_type size); template S make_sequence(typename S::size_type size, typename S::value_type v); template S make_sequence(std::initializer_list init); template decltype(auto) forward_sequence(A&& s); // equivalent to std::size(c) in c++17 template constexpr auto sequence_size(const C& c) -> decltype(c.size()); // equivalent to std::size(a) in c++17 template constexpr std::size_t sequence_size(const T (&a)[N]); /******************************** * make_sequence implementation * ********************************/ namespace detail { template struct sequence_builder { using value_type = typename S::value_type; using size_type = typename S::size_type; inline static S make(size_type size) { return S(size); } inline static S make(size_type size, value_type v) { return S(size, v); } inline static S make(std::initializer_list init) { return S(init); } }; template struct sequence_builder> { using sequence_type = std::array; using value_type = typename sequence_type::value_type; using size_type = typename sequence_type::size_type; inline static sequence_type make(size_type /*size*/) { return sequence_type(); } inline static sequence_type make(size_type /*size*/, value_type v) { sequence_type s; s.fill(v); return s; } inline static sequence_type make(std::initializer_list init) { sequence_type s; std::copy(init.begin(), init.end(), s.begin()); return s; } }; } template inline S make_sequence(typename S::size_type size) { return detail::sequence_builder::make(size); } template inline S make_sequence(typename S::size_type size, typename S::value_type v) { return detail::sequence_builder::make(size, v); } template inline S make_sequence(std::initializer_list init) { return detail::sequence_builder::make(init); } /*********************************** * forward_sequence implementation * ***********************************/ namespace detail { template struct sequence_forwarder_impl { template static inline R forward(const T& r) { R ret; std::copy(std::begin(r), std::end(r), std::begin(ret)); return ret; } }; template struct sequence_forwarder_impl().resize( std::declval()))>> { template static inline auto forward(const T& r) { return R(std::begin(r), std::end(r)); } }; template struct sequence_forwarder : sequence_forwarder_impl { }; template struct sequence_forwarder { template static inline T&& forward(T&& t) noexcept { return std::forward(t); } }; template using forwarder_type = detail::sequence_forwarder< std::decay_t, std::remove_cv_t> >; } template inline decltype(auto) forward_sequence(typename std::remove_reference::type& s) { using forwarder = detail::forwarder_type; return forwarder::forward(std::forward(s)); } template inline decltype(auto) forward_sequence(typename std::remove_reference::type&& s) { using forwarder = detail::forwarder_type; static_assert(!std::is_lvalue_reference::value, "Can not forward an rvalue as an lvalue."); return forwarder::forward(std::move(s)); } /******************************** * sequence_size implementation * ********************************/ // equivalent to std::size(c) in c++17 template constexpr auto sequence_size(const C& c) -> decltype(c.size()) { return c.size(); } // equivalent to std::size(a) in c++17 template constexpr std::size_t sequence_size(const T (&)[N]) { return N; } /**************************** * are_equivalent_sequences * ****************************/ template inline bool are_equivalent_sequences(const E1& e1, const E2& e2) { return std::equal(e1.cbegin(), e1.cend(), e2.cbegin(), e2.cend()); } } #endif