我想以某种方式将这些模板合并为一个:
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; }
};
(后面是Mul,Div等的相同代码),其中所有代码都相同, 除了实际的“+”,“ - ”(和“StupidAdd”,“StupidSub”等)。
这些愚蠢的“仿函数”随后被另一个模板使用。 如何在没有预处理器的情况下避免重复? (我进入模板的原因是为了避免预处理器)
也就是说,如何将算术运算符传递给模板?
答案 0 :(得分:7)
也许您可以使用std::plus<T>
,std::minus<T>
,std::multiplies<T>
和std::divides<T>
。但是,只有当两个操作数属于同一类型时,或者如果左侧操作数可以转换为第一个类型,它们才有效。
除了使用预处理器之外,我没有看到任何方法来实现您要做的事情。不想要宏的任何好理由?
如果你想确保返回类型足够大以包含结果,你可以这样做:
#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
}
在这里,我使用Boost MPL来编写largest
元函数,但如果你不能使用Boost(由两种类型和bool参数化的类模板,你可以编写自己的if
元函数,专门针对真假)。
要确定表达式的返回类型,您还可以查看boost::result_of,如果我理解正确的话,它等同于C ++ 0x中即将出现的decltype
运算符。
答案 1 :(得分:3)
谢谢吕克,这很酷。 我终于以一种更简单的方式做到了:
#include <functional>
template <
class Result,
class T1,
class T2,
template <class ReturnType> class BinaryOp>
class Stupido
{
public:
T1 _a; T2 _b;
Stupido(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return BinaryOp<Result>()((Result)_a,(Result)_b); }
};
在实例化Stupido时使用“加号”,“减号”。 “结果”的演员阵容足以满足我的需求(int + double =&gt; double + double =&gt; double)
答案 2 :(得分:3)
我认为OldCoder的解决方案有所改进:
#include <functional>
template <class Result,
template <class Result> class BinaryOp>
struct Stupido
{
template <typename T1, typename T2>
Result operator()(const T1& a, const T2& b) { return BinaryOp<Result>()((Result)a,(Result)b); }
};
这样可以将呼叫设为:
Stupido<int, std::plus > stup;
int result = stup(3.0f, 2.0);
并且相同的函数对象可以与多个操作数一起使用,因此可以将其传递给std::transform
调用。
我相信必须有一种方法可以从模板声明中删除一个结果,但我无法找到它。
答案 3 :(得分:0)
我使用C ++ 0x decltype和auto的新定义。您仍然需要定义类,但使用这些类,您可以更好地定义它们。他们仍然需要做大量的工作来定义,但至少使用它们会相当清晰。特别是,您可以使用decltype / auto来推断出正确的返回类型,而不必明确指定它。
最近的编译器有很多版本 - 英特尔C ++,g ++,Comeau,VC ++ 2010的测试版,甚至是Borland / Inprise / Embarcadero /本周新名称的最新版本。