include/unifex/adapt_stream.hpp (74 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <unifex/stream_concepts.hpp> #include <functional> #include <type_traits> #include <unifex/detail/prologue.hpp> namespace unifex { namespace _adapt_stream { template <typename Stream, typename NextAdaptFunc, typename CleanupAdaptFunc> struct _adapted { struct type; }; template <typename Stream, typename NextAdaptFunc, typename CleanupAdaptFunc = void> using adapted = typename _adapted< remove_cvref_t<Stream>, std::decay_t<NextAdaptFunc>, std::decay_t<CleanupAdaptFunc>>::type; template <typename Stream, typename NextAdaptFunc, typename CleanupAdaptFunc> struct _adapted<Stream, NextAdaptFunc, CleanupAdaptFunc>::type { Stream innerStream_; NextAdaptFunc nextAdapter_; CleanupAdaptFunc cleanupAdapter_; friend auto tag_invoke(tag_t<next>, type& s) -> std::invoke_result_t<NextAdaptFunc&, next_sender_t<Stream>> { return std::invoke(s.nextAdapter_, next(s.innerStream_)); } friend auto tag_invoke(tag_t<cleanup>, type& s) -> std::invoke_result_t<CleanupAdaptFunc&, cleanup_sender_t<Stream>> { return std::invoke(s.cleanupAdapter_, cleanup(s.innerStream_)); } }; template <typename Stream, typename AdaptFunc> struct _adapted<Stream, AdaptFunc, void> { struct type; }; template <typename Stream, typename AdaptFunc> struct _adapted<Stream, AdaptFunc, void>::type { Stream innerStream_; AdaptFunc adapter_; friend auto tag_invoke(tag_t<next>, type& s) -> std::invoke_result_t<AdaptFunc&, next_sender_t<Stream>> { return std::invoke(s.adapter_, next(s.innerStream_)); } friend auto tag_invoke(tag_t<cleanup>, type& s) -> std::invoke_result_t<AdaptFunc&, cleanup_sender_t<Stream>> { return std::invoke(s.adapter_, cleanup(s.innerStream_)); } }; } // namespace _adapt_stream namespace _adapt_stream_cpo { inline const struct _fn { template <typename Stream, typename AdapterFunc> auto operator()(Stream&& stream, AdapterFunc&& adapt) const -> _adapt_stream::adapted<Stream, AdapterFunc> { return {(Stream &&) stream, (AdapterFunc &&) adapt}; } template < typename Stream, typename NextAdapterFunc, typename CleanupAdapterFunc> auto operator()( Stream&& stream, NextAdapterFunc&& adaptNext, CleanupAdapterFunc&& adaptCleanup) const -> _adapt_stream::adapted<Stream, NextAdapterFunc, CleanupAdapterFunc> { return { (Stream &&) stream, (NextAdapterFunc &&) adaptNext, (CleanupAdapterFunc &&) adaptCleanup}; } } adapt_stream {}; } // namespace _adapt_stream_cpo using _adapt_stream_cpo::adapt_stream; } // namespace unifex #include <unifex/detail/epilogue.hpp>