/* Copyright 2016-2017 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_TYPE_RESTITUTION_HPP #define BOOST_POLY_COLLECTION_DETAIL_TYPE_RESTITUTION_HPP #if defined(_MSC_VER) #pragma once #endif #include #include #include #include namespace boost{ namespace poly_collection{ namespace detail{ /* Given types Ts..., a const std::type_info& info and a local_base_iterator * it, we denote by restitute(info,it): * - a local_iterator from it, if info==typeid(Ti) for some Ti in Ts... * - it otherwise. * * Using this notation, restitute_range(f,args...)(s) resolves to * f(restitute(info,begin),restitute(info,end),args...) where * info=s.type_info(), begin=s.begin(), end=s.end(). */ template struct restitute_range_class; template struct restitute_range_class: restitute_range_class { using super=restitute_range_class; using super::super; template auto operator()(SegmentInfo&& s) ->decltype(std::declval()(s.begin(),s.end())) { using traits=iterator_traits; using local_iterator=typename traits::template local_iterator; if(s.type_info()==typeid(T)) return (this->f)( local_iterator{s.begin()},local_iterator{s.end()}); else return super::operator()(std::forward(s)); } }; template struct restitute_range_class { restitute_range_class(const F& f):f(f){} template auto operator()(SegmentInfo&& s) ->decltype(std::declval()(s.begin(),s.end())) { return f(s.begin(),s.end()); } F f; }; template auto restitute_range(const F& f,Args&&... args) ->restitute_range_class< decltype(tail_closure(f,std::forward(args)...)), Ts... > { return tail_closure(f,std::forward(args)...); } /* restitute_iterator(f,args2...)(index,it,args1...) resolves to * f(restitute(index,it),args1...,args2...). */ template struct restitute_iterator_class; template struct restitute_iterator_class: restitute_iterator_class { using super=restitute_iterator_class; using super::super; template auto operator()( const std::type_info& info,Iterator&& it,Args&&... args) ->decltype( std::declval() (std::forward(it),std::forward(args)...)) { using traits=iterator_traits::type>; using local_iterator=typename traits::template local_iterator; if(info==typeid(T)) return (this->f)( local_iterator{it},std::forward(args)...); else return super::operator()( info,std::forward(it),std::forward(args)...); } }; template struct restitute_iterator_class { restitute_iterator_class(const F& f):f(f){} template auto operator()( const std::type_info&,Iterator&& it,Args&&... args) ->decltype( std::declval() (std::forward(it),std::forward(args)...)) { return f(std::forward(it),std::forward(args)...); } F f; }; template auto restitute_iterator(const F& f,Args&&... args) ->restitute_iterator_class< decltype(tail_closure(f,std::forward(args)...)), Ts... > { return tail_closure(f,std::forward(args)...); } /* binary_restitute_iterator(f,args...)(index1,it1,index2,it2) resolves * to f(restitute(index1,it1),restitute(index2,it2),args...). */ template struct binary_restitute_iterator_class { binary_restitute_iterator_class(const F& f):f(f){} template auto operator()( const std::type_info& info1,Iterator1&& it1, const std::type_info& info2,Iterator2&& it2) ->decltype( std::declval() (std::forward(it1),std::forward(it2))) { return restitute_iterator(*this)( info2,std::forward(it2),info1,std::forward(it1)); } template auto operator()( Iterator2&& it2,const std::type_info& info1,Iterator1&& it1) ->decltype( std::declval() (std::forward(it1),std::forward(it2))) { return restitute_iterator(f)( info1,std::forward(it1),std::forward(it2)); } F f; }; template auto binary_restitute_iterator(const F& f,Args&&... args) ->binary_restitute_iterator_class< decltype(tail_closure(f,std::forward(args)...)), Ts... > { return tail_closure(f,std::forward(args)...); } } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif