/*
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