/* Copyright 2016-2018 Joaquin M Lopez Munoz. * 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) * * See http://www.boost.org/libs/poly_collection for library home page. */ #ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP #define BOOST_POLY_COLLECTION_DETAIL_FUNCTIONAL_HPP #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include /* Assorted functional utilities. Much of this would be almost trivial with * C++14 generic lambdas. */ #if BOOST_WORKAROUND(BOOST_MSVC,>=1910) /* https://lists.boost.org/Archives/boost/2017/06/235687.php */ #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \ struct name \ { \ template \ auto operator()(Args&&... args)const \ { \ return f(std::forward(args)...); \ } \ }; #else #define BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(name,f) \ struct name \ { \ template \ auto operator()(Args&&... args)const-> \ decltype(f(std::forward(args)...)) \ { \ return f(std::forward(args)...); \ } \ }; #endif namespace boost{ namespace poly_collection{ namespace detail{ template struct tail_closure_class { tail_closure_class(const F& f,std::tuple t):f(f),t(t){} template using return_type=decltype( std::declval()(std::declval()...,std::declval()...)); template return_type call(mp11::index_sequence,Args&&... args) { return f(std::forward(args)...,std::get(t)...); } template return_type operator()(Args&&... args) { return call( mp11::make_index_sequence{}, std::forward(args)...); } F f; std::tuple t; }; template tail_closure_class tail_closure(const F& f,Args&&... args) { return {f,std::forward_as_tuple(std::forward(args)...)}; } template struct head_closure_class { head_closure_class(const F& f,std::tuple t):f(f),t(t){} template using return_type=decltype( std::declval()(std::declval()...,std::declval()...)); template return_type call(mp11::index_sequence,Args&&... args) { return f(std::get(t)...,std::forward(args)...); } template return_type operator()(Args&&... args) { return call( mp11::make_index_sequence{}, std::forward(args)...); } F f; std::tuple t; }; template head_closure_class head_closure(const F& f,Args&&... args) { return {f,std::forward_as_tuple(std::forward(args)...)}; } template struct cast_return_class { cast_return_class(const F& f):f(f){} template ReturnType operator()(Args&&... args)const { return static_cast(f(std::forward(args)...)); } F f; }; template cast_return_class cast_return(const F& f) { return {f}; } template struct deref_to_class { deref_to_class(const F& f):f(f){} template auto operator()(Args&&... args)->decltype(std::declval()(*args...)) { return f(*args...); } F f; }; template deref_to_class deref_to(const F& f) { return {f}; } template struct deref_1st_to_class { deref_1st_to_class(const F& f):f(f){} template auto operator()(Arg&& arg,Args&&... args) ->decltype(std::declval()(*arg,std::forward(args)...)) { return f(*arg,std::forward(args)...); } F f; }; template deref_1st_to_class deref_1st_to(const F& f) { return {f}; } struct transparent_equal_to { template auto operator()(T&& x,U&& y)const noexcept(noexcept(std::forward(x)==std::forward(y))) ->decltype(std::forward(x)==std::forward(y)) { return std::forward(x)==std::forward(y); } }; } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif