我读到函数call()也可以重载。 http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
以下是什么意思?
有效。
template<typename T, typename Comp>
struct bind{
T v;
Comp comp;
bool operator()(const T& b){
return comp(b,v);
}
};
int main(){
bind<int, less<int> > b;
b.v = 2;
cout << b(3) << "\n";
}
答案 0 :(得分:2)
这意味着如果您创建类型为bind<>
的对象,则可以将函数调用运算符应用于该对象。
像这样:
bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";
该片段可能会在标准输出上打印“true”。
答案 1 :(得分:1)
如果您有一个名为foo
的类,我确信您了解调用该类型对象的成员函数意味着什么:
foo f;
f.bar();
您可能还了解可以超载某些操作。例如,您可以为operator+
重载foo
,以便您可以执行以下操作:
foo f, g;
f + g;
现在你也可以为一个类重载operator()
,这允许你像调用它一样调用它:
foo f;
f();
是的,f
不是函数,但是类型的对象重载operator()
。执行此操作的类类型称为仿函数或函数对象。
在您给出的示例中,bind
是一个仿函数。当您创建该类型的对象时,您可以将其称为函数,并将其传递给const T&
,它将返回bool
给您。 operator()
的实现实际上调用了存储在comp
中的函数,并将传递给T
,operator()
的{{1}}对象和成员对象{ {1}}类型的{1}}。
答案 2 :(得分:1)
就目前而言,除了“语法错误”之外,它并不意味着什么。例如:
template<T, Op>
这是不允许的。对于每个模板参数,您需要指定它是一种类型(使用class
还是typename
)还是非类型参数,例如int
。由于明显的意图是这两个都应该是类型参数,你需要类似的东西:
template <class T, class Op>
或:
template <typename T, typename Op>
对于这种情况,class
和typename
之间的含义没有区别。
击>
struct bind{
T v;
离开v
未初始化将导致未定义的行为,因此您可能不希望允许这样做。您通常会通过添加以T为参数的构造函数并将v
初始化为该值来阻止它:
bind(T const &v) : v(v) {}
当您包含这样的构造函数时,编译器不会自动生成默认构造函数,因此不再可能创建bind
未初始化v
的对象 - 正是我们想要的。
虽然创建了comp
对象:
Op comp;
是相当无害的,也是非常不必要的。您也可以与使用Op()
创建的临时实例进行比较,在这种情况下:
bool operator()(const T& a){
return comp(a,v);
}
......会变成这样的东西(简单地删除Op comp;
):
bool operator()(T const &a) {
return Op()(a, v);
}
即使有更正,我也会认为此代码已过时。在C ++ 98/03中,在需要为算法提供仿函数的情况下它会很有用,例如:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
bind<int, std::less<int> >(5));
...将a
的数字复制到b
,删除少于5的数字。
但是,在C ++ 11中,大多数(如果不是全部)使用这个bind
应该写成lambda而不是,所以上面的位会变成这样:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
[](int x) { return x < 5; });
这不仅更短,而且(至少在你习惯之后)比使用std::less
和bind
组合一个函数要简单得多。它通常不会对运行时效率产生任何影响 - lambda基本上是生成类模板的“简写”方式,因此它生成的内容最终与使用bind
的代码非常相似。 / p>