/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_FORWARDING_H #define CXX_FORWARDING_H #include #include #include "evaluation_tools.h" #include "mp.h" #include "rules.h" #include "tuple.h" // XXX This file is UNFINISHED. It is/was meant to use for extending flintxx by // compisition, in particular for the NTL wrapper. // Ask Tom (e_mc_h2@web.de) if you want to use it. namespace flint { namespace forwarding { // Specialise this to enable forwarding of your class. template struct enable : mp::false_ { }; } // forwarding namespace rules { template struct print::underlying_t> > >::type> { static void doit(const T& t, std::ostream& o) { typedef typename forwarding::enable et; print::doit(et::get_underlying(t), o); } }; template struct to_string::underlying_t> > >::type> { static std::string get(const T& t, int base) { typedef typename forwarding::enable et; return to_string::get( et::get_underlying(t), base); } }; namespace rdetail { template struct maybe_forward { typedef T underlying_t; static const T& get_underlying(const T& t) {return t;} static T& get_underlying(T& t) {return t;} }; template struct maybe_forward >::type> : forwarding::enable { }; template class Wrapped, class T, class U> struct fwd_enable2 : mp::enable_if::underlying_t, typename maybe_forward::underlying_t, void> >, mp::or_< typename forwarding::enable, typename forwarding::enable > > > { typedef Wrapped< typename maybe_forward::underlying_t, typename maybe_forward::underlying_t, void> wrapped_t; }; } // rdetail template struct assignment::type> { static void doit(T& t, const U& u) { rdetail::fwd_enable2::wrapped_t::doit( rdetail::maybe_forward::get_underlying(t), rdetail::maybe_forward::get_underlying(u)); } }; template struct cmp::type> { static int get(const T& t, const U& u) { return rdetail::fwd_enable2::wrapped_t::get( rdetail::maybe_forward::get_underlying(t), rdetail::maybe_forward::get_underlying(u)); } }; template struct equals::type> { static bool get(const T& t, const U& u) { return rdetail::fwd_enable2::wrapped_t::get( rdetail::maybe_forward::get_underlying(t), rdetail::maybe_forward::get_underlying(u)); } }; template struct conversion::underlying_t> > >::type> { static T get(const U& u) { return conversion::underlying_t>::get( forwarding::enable::get_underlying(u)); } }; // TODO automatically convert fwd to fwd ? // TODO instantiate_temporaries ? namespace rdetail { template struct needs_forwarding : mp::false_ { }; template struct needs_forwarding : forwarding::enable { }; template struct needs_forwarding > : mp::or_, needs_forwarding > { }; template struct translate { typedef Data type; static type doit(const Data& d) {return d;} }; template struct translate { typedef maybe_forward fw; typedef typename fw::underlying_t type; static type doit(const Wrapped& d) { return fw::get_underlying(d); } }; template struct translate > { typedef translate htranslator; typedef translate ttranslator; typedef tuple type; static type doit(const tuple& d) { return type(htranslator::doit(d.head), ttranslator::doit(d.tail)); } }; template struct can_forward { typedef rdetail::translate translator; typedef typename translator::type translated_t; typedef typename mp::find_evaluation< Op, translated_t, result_is_temporary>::type rule_t; static const bool val = traits::is_implemented::val; }; template struct can_forward >::type> { static const bool val = false; }; } template struct evaluation >::type> { typedef rdetail::translate translator; typedef typename translator::type translated_t; typedef typename mp::find_evaluation< Op, translated_t, result_is_temporary>::type rule_t; typedef typename rule_t::temporaries_t temporaries_t; // TODO repackaging typedef typename rule_t::return_t return_t; static void doit(const Data& input, temporaries_t temps, return_t* output) { rule_t::doit(translator::doit(input), temps, output); } }; } //rules } // flint #endif