0

我读到函数调用()也可以重载。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";
}
4

3 回答 3

2

这意味着如果您创建一个类型为 的对象bind<>,您可以将函数调用运算符应用于该对象。

像这样:

bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";

该片段可能会在标准输出上打印“true”。

于 2013-02-15T20:40:12.993 回答
1

如果你有一个名为 的类foo,我相信你明白调用该类型对象的成员函数意味着什么:

foo f;
f.bar();

您可能还了解您可以重载某些操作。例如,您可以重载operator+forfoo以便您可以执行以下操作:

foo f, g;
f + g;

现在你也可以重载operator()一个类,这样你就可以像调用一个函数一样调用它:

foo f;
f();

是的,f不是函数,而是重载的类类型的对象operator()。执行此操作的类类型称为函子或函数对象。

在您给出的示例中,bind是一个函子。当您创建该类型的对象时,您可以像调用函数一样调用它,将 a 传递给它const T&,它会返回 abool给您。的实现operator()实际上调用了存储在 中的函数comp,将T您传递给operator(),的对象和类型a的成员对象都传递给它。vT

于 2013-02-15T20:44:01.170 回答
1

就目前而言,除了“语法错误”之外,它并不意味着什么。例如:

template<T, Op>

这根本是不允许的。对于每个模板参数,您需要指定它是类型(使用classtypename)还是非类型参数,例如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));

...这会将数字从 复制ab,删除小于 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::lessbind组合一个函数要简单得多。它通常不会对运行时效率产生任何影响——lambda 基本上是一种生成类模板的“速记”方式,因此它生成的内容最终与使用bind.

于 2013-02-15T21:07:23.083 回答