[英]Passing a functor as C++ template parameter
As an exercise for my personal enlightenment, I implement vector math with expression templates. 作为我个人启蒙的练习,我用表达模板实现了矢量数学。 I want to implement some operations that apply the same unary function to all elements to a vector expression. 我想实现一些操作,将相同的一元函数应用于向量表达式的所有元素。 So far, I do this. 到目前为止,我这样做了。
My base vector expression template is implemented like this 我的基本载体表达模板是这样实现的
template <typename E>
class VectorExpr {
public:
int size() const { return static_cast<E const&>(*this).size(); }
float operator[](int i) const { return static_cast<E const&>(*this)[i]; }
operator E& () { return static_cast<E&>(*this); }
operator E const& () const { return static_cast<const E&>(*this); }
}; // class VectorExpr
Then, an object supposed to be a vector will look like this 然后,一个应该是矢量的对象看起来像这样
class Vector2 : public VectorExpr<Vector2> {
public:
inline size_t size() const { return 2; }
template <typename E>
inline Vector2(VectorExpr<E> const& inExpr) {
E const& u = inExpr;
for(int i = 0; i < size(); ++i)
mTuple[i] = u[i];
}
private:
float mTuple[2];
};
Let's say I want to apply std::sin to all elements of an expression 假设我想将std :: sin应用于表达式的所有元素
template <typename E>
class VectorSin : public VectorExpr<VectorSin<E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return std::sin(mV[i]); }
};
Question => If I want to add more functions, I copy-paste what I do for the sin function, for every single function (like cos, sqrt, fabs, and so on). 问题=>如果我想添加更多功能,我会为每个函数(如cos,sqrt,fabs等)复制粘贴我为sin函数所做的操作。 How I can avoid this kind of copy-pasting ? 我怎么能避免这种复制粘贴? I tried things and figured out I'm still low in template-fu. 我尝试了一些东西,并发现我的模板效率仍然很低。 No boost allowed ^^ 没有提升允许^^
template <typename F, typename E>
class VectorFunc : public VectorExpr<VectorFunc<F, E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return f(mV[i]); }
// this assumes the Functor f is default constructible, this is
// already not true for &std::sin. Adding the constructor that
// takes f, is left as an exercise ;)
F f;
};
In addition to the answer by pmr , The standard <cmath>
functions aren't functors, so you couldn't use them directly to specify unique specialisations of your class - ie you wouldn't have a separate template instantiation for std::sin versus std::cos (which is what I gather you're aiming for? correct me if I've misunderstood you on that). 除了pmr的答案之外 ,标准的<cmath>
函数不是仿函数,所以你不能直接使用它们来指定类的唯一特化 - 即你不会为std :: sin单独的模板实例化与std :: cos(我收集你的目标是什么?如果我误解了你,请纠正我)。
You could create a wrapper in order to map a function pointer to a distinct type, eg 您可以创建一个包装器,以便将函数指针映射到不同的类型,例如
#include <iostream>
template< void (*FuncPtr)() > struct Func2Type
{
void operator() () { FuncPtr(); }
};
void Hello() { std::cout << "Hello" << std::endl; }
void World() { std::cout << "world" << std::endl; }
int main()
{
Func2Type<Hello> test1;
Func2Type<World> test2;
test1();
test2();
}
That way you could use them as template arguments in the same way as a normal functor class 这样你就可以像普通仿函数一样使用它们作为模板参数
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.