Effective STL

【Effective STL(6)】仿函数、仿函数类、函数等

2018-03-15  本文已影响14人  downdemo

38 把仿函数类设计为用于值传递

// for_each声明
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
class DoSomething : public unary_function<int, void> {
public:
    void operator()(int x) {...}
    ...
};
typedef deque<int>::iterator DequeIntIter;
deque<int> di;
...
DoSomething d; // 建立一个函数对象
...
for_each<DequeIntIter, DoSomething&>(di.begin(), di.end(), d);
template<typename T> // Big Polymorphic Functor Class
class BPFC : public unary_function<T, void> {
private:
    Widget w; // 这个类包含很多数据
    Int x;
    ```
public:
    virtual void operator()(const T& val) const;
    ...
};
template<typename T>
class BPFCImpl : public unary_function<T, void> {
private:
    Widget w; // 以前在BPFC里的所有数据现在在这里
    int x;
    ...
    virtual ~BPFCImpl();
    virtual void operator()(const T& val) const;
    friend class BPFC<T>; // 让BPFC可以访问这些数据
};
template<typename T>
class BPFC : public unary_function<T, void> {
private:
    BPFCImpl<T> *pImpl; // BPFC唯一的数据
public:
    void operator()(const T& val) const
    {
        pImpl->operator() (val);
    }
    ...
};

39 用纯函数做判断式

class BadPredicate : public unary_function<Widget, bool> {
public:
    BadPredicate(): timesCalled(0) {}
    bool operator()(const Widget&)
    {  
        return ++timesCalled == 3;
    }
private:
    size_t timesCalled;
};

vector<Widget> vw;
...
vw.erase(remove_if(vw.begin(), vw.end(), BadPredicate()), vw.end());
template <typename FwdIterator, typename Predicate>
FwdIterator remove_if(FwdIterator begin, FwdIterator end, Predicate p)
{
    begin = find_if(begin, end, p);
    if (begin == end) return begin;
    else
    {
        FwdIterator next = begin;
        return remove_copy_if(++next, end, begin, p);
    }
}
class BadPredicate : public unary_function<Widget, bool> {
public:
    bool operator()(const Widget&) const
    {
        return ++timesCalled == 3; // 错误,不能改变局部数据
    }
};
bool anotherBadPredicate(const Widget&, const Widget&)
{
    static int timesCalled = 0; // 错误,纯函数不能有状态
    return ++timesCalled == 3;
}

40 使仿函数类可适配

list<Widget*> widgetPtrs;
bool f(const Widget *pw);
list<Widget*>::iterator i = find_if(widgetPtrs.begin(), widgetPtrs.end(), f);
if (i != widgetPtrs.end()) { ... }
list<Widget*>::iterator i =
    find_if(widgetPtrs.begin(), widgetPtrs.end(), not1(f));
list<Widget*>::iterator i =
    find_if(widgetPtrs.begin(), widgetPtrs.end(), not1(ptr_fun(f)));
template<typename T>
class MeetsThreshold : public std::unary_function<Widget, bool> {
private:
    const T threshold;
public:
    MeetsThreshold(const T& threshold);
    bool operator() (const Widget&) const;
...
};
struct WidgetNameCompare : public std::binary_function<Widget, Widget, bool> {
    bool operator()(const Widget& lhs, const Widget& rhs) const;
};
list<Widget> widgets;
...
list<Widget>::reverse_iterator i1 = 
    find_if(widgets.rbegin(), widgets.rend(), not1(MeetsThreshold<int>(10)));
Widget w(构造函数实参);
list<Widget>::iterator i2 = 
    find_if(widgets.begin(), widgets.end(), bind2nd(WidgetNameCompare(), w);

41 了解使用ptr_fun、mem_fun和mem_fun_ref的原因

f(x); // 语法#1:f是一个非成员函数
x.f(); // 语法#2:f是一个成员函数且x是一个对象或对象的引用
p->f(); // 语法#3:当f是一个成员函数且p是一个对象的指针
void test(Widget& w);
vector<Widget> vw;
for_each(vw.begin(), vw.end(), test); // 调用#1(可以编译)
class Widget {
public:
    void test(); // 失败则把*this标记为failed
};
for_each(vw.begin(), vw.end(), &Widget::test); // 调用#2(不能编译)
// 对指针的容器测试
list<Widget*> lpw;
for_each(lpw.begin(), lpw.end(), &Widget::test); // 调用#3(不能编译)
template<typename InputIterator, typename Function>
Function for_each(InputIterator begin, InputIterator end, Function f)
{
    while (begin != end) f(*begin++);
}
// 用于不带参数的non-const成员函数的mem_fun声明
template<typename R, typename C> // C是类,R是成员函数的返回类型
mem_fun_t<R,C> mem_fun(R(C::*pmf)());
for_each(lpw.begin(), lpw.end(), mem_fun(&Widget::test)); // 可以编译
for_each(vw.begin(), vw.end(), ptr_fun(test)); // 同调用#1

42 确定less<T>表示operator<

class A {
public:
    ...
    int x() const;
    int y() const;
    ...
};
bool operator<(const A& lhs, const A& rhs)
{
    return lhs.x() < rhs.x();
}
template<>
struct std::less<A> : public std::binary_function<A, A, bool> {
    bool operator() (const A& lhs, const A& rhs) const
    {
        return lhs.y() < rhs.y();
    }
}
namespace std {
    template<typename T>
    struct less<shared_ptr<T>>
    : public binary function<boost::shared_ptr<T>, shared_ptr<T> bool> {
        bool operator()(const boost::shared_ptr<T>& a, const boost::shared_ptr<T>& b) const
        {
            return less<T*>()(a.get(),b.get());
        }
    };
}
struct yCompare : public binary_function<A, A, bool> {
    bool operator()(const A& lhs, const A& rhs) const
    {
        return lhs.y() < rhs.y();
    }
};
 multiset<A, yCompare> a;
上一篇下一篇

猜你喜欢

热点阅读