{技术}{讨论}{C++}STL函数对象为何是通过类模板实现而非普通类的成员函数模板实现

11 views
Skip to first unread message

Scan

unread,
Nov 11, 2009, 5:18:44 AM11/11/09
to TopLanguage
小弟看的书不多, 一时不明白这个道理

比如
template<typename T>
struct Greater
{
bool operator () (const T& lhs, const T& rhs)
{
return lhs > rhs;
}
};

struct Less
{
template<typename T>
bool operator () (const T& lhs, const T& rhs)
{
return lhs < rhs;
}
};

单就使用而言, 上面的Less肯定更方便, 比如语法
sort(vec.begin(), vec.end(), Greater<int>());
sort(vec.begin(), vec.end(), Less());
包括在其他算法模板当中, 使用Less的话, 可能有时候可以绕过traits实现某些功能

但其实STL等库充斥着类模板, 即使当时使用函数模板也能实现功能

我勉强想一下:
当对上面Greater和Less多次调用的时候, Greater一直都是用户直接指定的类型, 所以都能立刻定位到()运算符, 而Less在多次
模板实例化后会有多个函数重载, 匹配正确的函数签名还是比Greater慢了, 两种实现方法, 是在编译期存在速度上的差异?

Ian Yang

unread,
Nov 11, 2009, 4:08:41 PM11/11/09
to pon...@googlegroups.com
第二种写法没法满足Adaptable Functor的requirements, 无法用在需要Adaptable Functor concept的地方,比如bind1st。其它没区别

-------
Sincerely, Ian Yang




2009/11/11 Scan <yxs...@gmail.com>

陈忠磊

unread,
Nov 11, 2009, 9:50:13 PM11/11/09
to pon...@googlegroups.com

struct Less
{
    template<typename T>
    bool operator () (const T& lhs, const T& rhs)
    {
        return lhs < rhs;
    }
};

template<typename FT, typename T>
class FirstBinder
{
public:
    FirstBinder(FT fn, const T& p1st):
      m_fn(fn),
      m_p1st(p1st)
      {

      }

    // template<typename SecondT>
    bool operator () (const T& p2nd)
    {
        return m_fn(m_p1st, p2nd);
    }

private:
    FT          m_fn;
    const T&    m_p1st;
};

template<typename FT, typename FirstT>
inline FirstBinder<FT, FirstT> bindFirst(FT fn, const FirstT& p1st)
{
    return FirstBinder<FT, FirstT>(fn, p1st);
}; 

int main() 
{
    cout << bindFirst(Less(), 5.0)(4);
}
 
 
 
这是我尝试的bindFirst
不过, 这不是重点
我想说的是, 由于STL内部需要一系列的typedefs, 所以就将binary_function这样的traits抛给用户, 需要库用户来记住某些库细节, 这是必须的吗?
以上面的例子来说, 库内置成员函数模板形式的函数对象看起来对库用户来说更容易上手, 假如采用这种实现, 将原来位于函数对象内部的traits分离到外部, 尽量简化函数对象的实作要求, 是不可能的? 由于小弟并没有实现过泛型库, 所以可能没意识到库的其他方面诸多实现考虑, 所以才提出这个疑问: STL的函数类模板形式, 这个咋看这下使用稍嫌麻烦的形式, 是实现STL这样泛型库整个体系必须的要求吗? 那么这种要求主要是出于何种考虑?

陈忠磊

unread,
Nov 11, 2009, 9:52:35 PM11/11/09
to pon...@googlegroups.com
谢谢lan Yang的点拨, 开始我确实没意识到这么个问题
但似乎不全是这个原因?
或许是因为有其他无论如何也必须采用类模板才能兼顾STL方方面面的考虑?

2009/11/12 Ian Yang <doit...@gmail.com>

孙朝阳

unread,
Nov 13, 2009, 1:08:10 AM11/13/09
to pon...@googlegroups.com
据我所知,这主要是当年的编译器大多不能很好支持成员模板函数。出自哪本书想不起来了。

另外,在boost里面,可以看看MPL和fusion,里面,成员函数是模板的情况则非常普遍了。

---------------------------------------
绝圣弃知,大盗乃止;擿玉毁珠,小盗不起;


2009/11/12 陈忠磊 <yxs...@gmail.com>

Ian Yang

unread,
Nov 13, 2009, 3:22:48 AM11/13/09
to pon...@googlegroups.com
早绑定(模板类)可以早点报错, 迟绑定(模板成员函数)灵活,但是报错离出错地方远,而且用来比较多种数据类型会多次模板实例化。

MPL和fusion是另外一种场景了,而且也不是成员函数模板,而且是嵌套类, 外层类当成函数调用,传的参数就是模板参数了

struct Func {
    template<typename T>
    struct apply {
        typedef XXX result;
    };
};

Func::apply<T>::result 就相当于函数调用, T是参数, 整个表达式的类型就是返回值。

-------
Sincerely, Ian Yang


Sent from Shanghai, 31, China

2009/11/13 孙朝阳 <wing...@gmail.com>
Reply all
Reply to author
Forward
0 new messages