【问题标题】:Pass operator as function template parameter将运算符作为函数模板参数传递
【发布时间】:2013-06-23 01:43:54
【问题描述】:

我必须为我制作的一些非常复杂的对象重载基本算术运算符。至此,我已经成功实现operator*;现在我需要operator+ 等。operator* 的代码非常大,但operator*operator+ 之间的唯一区别将是我在某些复数上使用+ 而不是* 的一行.这条线将在一个被多次调用的循环内,所以我希望它高效,这似乎意味着没有函数指针。 (如果我错了,请纠正我。)

这似乎是模板的完美用途。但我不知道正确的语法。我在 ComplicatedObject 类定义中想这样的事情:

template <typename ComplexBinaryOp>
ComplicatedObject BinaryOp(const ComplicatedObject& B) const {
  // Do lots of stuff
  for(unsigned int i=0; i<OneBazillion; ++i) {
    // Here, the f[i] are std::complex<double>'s:
    C.f[i] = ComplexBinaryOp(f[i], B.f[i]);
  }
  // Do some more stuff
  return C;
}

inline ComplicatedObject operator*(const ComplicatedObject& B) const {
  return BinaryOp<std::complex::operator*>(B);
}

inline ComplicatedObject operator+(const ComplicatedObject& B) const {
  return BinaryOp<std::complex::operator+>(B);
}

这个问题是相关的:"function passed as template argument"。但是作为模板参数传递的函数不是运算符。

我已经用我能想到的各种方式摆弄了语法,但是编译器总是抱怨语法不好。我该怎么做?

编辑:

为了清楚起见,我在上面的代码中包含了完整的解决方案,以及人们可能需要的其他概括:

template <typename ComplexBinaryOp>
ComplicatedObject BinaryOp(const ComplicatedObject& B) const {
  // Do lots of stuff
  for(unsigned int i=0; i<OneBazillion; ++i) {
    // Here, the f[i] are std::complex<double>'s:
    C.f[i] = ComplexBinaryOp()(f[i], B.f[i]); // Note extra ()'s
  }
  // Do some more stuff
  return C;
}

inline ComplicatedObject operator+(const ComplicatedObject& B) const {
  return BinaryOp<std::plus<std::complex<double> > >(B);
}

inline ComplicatedObject operator-(const ComplicatedObject& B) const {
  return BinaryOp<std::minus<std::complex<double> > >(B);
}

inline ComplicatedObject operator*(const ComplicatedObject& B) const {
  return BinaryOp<std::multiplies<std::complex<double> > >(B);
}

inline ComplicatedObject operator/(const ComplicatedObject& B) const {
  return BinaryOp<std::divides<std::complex<double> > >(B);
}

【问题讨论】:

  • std::complex 是类模板,所以需要std::complex&lt;double&gt;。但即便如此,complex&lt;T&gt;::operator*complex&lt;T&gt;::operator+ 也是成员函数。如果没有 complex&lt;T&gt; 的实例进行操作,你不能只是传递它们。
  • 发布您遇到的错误。
  • +1 有趣的问题。我还发现了这个问题——c++ pointers to operators 相关且有趣。

标签: c++ templates operator-overloading


【解决方案1】:

我认为 std::plus&lt;std::complex&gt;std::multiplies&lt;std::complex&gt; 是您正在寻找的内容,但我不能 100% 确定我理解您的问题(您的代码 sn-p 在您没有向我们展示的课程中吗?)

【讨论】:

  • +1,我认为这也是 OP 正在寻找的,但应该是 plus&lt;complex&lt;double&gt;&gt;multiplies&lt;complex&lt;double&gt;&gt;
  • @Praetorian: 所以plusmultiplies 可以在不指定std 范围的情况下使用?
  • +1 是的,这看起来像我想要的,好吧(尽管@Praetorian 是对的)。但我不太清楚如何使用这些功能。编译器反对我的行ComplexBinaryOp(f[i], B.f[i])。有什么帮助吗?
  • @keelar 这不是我的意思。 std::complex 是一个类模板,所以它需要专门用于一个类型。 std::plus&lt;std::complex&lt;double&gt;&gt; 等等。 (虽然你可以使用plusmultiplies unqualified,只要你有资格complex因为ADL
  • @me ComplexBinaryOp()(f[i], B.f[i]) 完成了这项工作。注意额外的括号。
【解决方案2】:

你有两个选择。在运行时传递函数:

#include <functional>

template <typename ComplexBinaryOp>
ComplicatedObject BinaryOp(const ComplicatedObject& B, ComplexBinaryOp op) const {
  // ...
    C.f[i] = op(f[i], B.f[i]);
  // ...
}

// functor wrapping member function pointer
BinaryOp(B, std::mem_fn(&std::complex<double>::operator+));

// standard-issue functor
BinaryOp(B, std::plus<std::complex<double>>());

或者在编译时传递:

// or another floating-point type
typedef double (*ComplexBinaryOp)(double, double);

template <ComplexBinaryOp op>
ComplicatedObject BinaryOp(const ComplicatedObject& B) const {
  // ...
    C.f[i] = op(f[i], B.f[i]);
  // ...
}

// non-member function
template<class T>
std::complex<T> add_complex(const std::complex<T>& a, const std::complex<T>& b) {
  return a + b;
}

// non-member function pointer
BinaryOp<add_complex<double>>(B);

我相信您也可以通过更改 ComplexBinaryOp 的定义来对成员函数指针执行相同的操作。

【讨论】:

  • 这些看起来很有用。我会尝试一下然后回复你。谢谢!
  • 在用std::multiplies 替换std::complex::operator* 等之后,我原来的语法工作得很好。你的也可以,但它们让我觉得不那么简单。
  • @Mike:是的,这也有效。不过,您必须说 ComplexBinaryOp()(foo, bar) 才能真正获得函子实例。这与我的第一个示例一样可以在内部或外部完成。
猜你喜欢
  • 2014-07-24
  • 1970-01-01
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-18
  • 2018-03-27
相关资源
最近更新 更多