I want to somehow merge templates like these into one:
template <class Result, class T1, class T2>
class StupidAdd
{
public:
T1 _a; T2 _b;
StupidAdd(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return _a+_b; }
};
template <class Result, class T1, class T2>
class StupidSub
{
public:
T1 _a; T2 _b;
StupidSub(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return _a-_b; }
};
(followed by the same code for Mul, Div, etc) where all the code is the same, except for the actual "+", "-" (and "StupidAdd", "StupidSub", etc).
These Stupid "functors" are then used by another template. How can I avoid the repetition, WITHOUT the preprocessor? (The reason I got into templates was to avoid the preprocessor)
That is, how can I pass arithmetic operators into a template?
Maybe you could use std::plus<T>
, std::minus<T>
, std::multiplies<T>
and std::divides<T>
. However, these will work only if both operands are of the same type, or probably if the left one can be converted to the type of the first one.
I don't see any way to achieve what you're trying to do, except by using the preprocessor. Any good reasons for not wanting macros ?
If you want to make sure the return type is large enough to contains the result, you could do something along this way:
#include <functional>
#include <boost/mpl/if_.hpp>
// Metafunction returning the largest type between T and U
// Might already exist in Boost but I can't find it right now...maybe
// boost::math::tools::promote_args
template <typename T, typename U>
struct largest :
boost::mpl::if_<
boost::mpl::bool_<(sizeof(T) > sizeof(U))>,
T,
U
>
{};
template <typename T, typename U, template <typename S> class Op>
struct Foo
{
typedef typename largest<T, U>::type largeType;
largeType bar(const T & t, const U & u)
{
return Op<largeType>()(t, u); // Applies operator+
}
};
int main()
{
Foo<int, double, std::plus> f;
double d = f.bar(12, 13.0); // takes int and double, returns double
}
Here, I used Boost MPL to write the largest
metafunction, but you could write your own if
metafunction if you cannot use Boost (class template parameterized by two types and a bool, specialized for true and false).
To determine the return type of an expression, you could also have a look at boost::result_of which, if I understand correctly, is equivalent to the upcoming decltype
operator in C++0x.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With