【问题标题】:Copying/assigning STL templates, std::less and std:greater复制/分配 STL 模板,std::less 和 std:greater
【发布时间】:2011-10-23 11:32:34
【问题描述】:

我需要在 std::less 和 std::greater 模板之间进行选择,并将其中一个存储在另一个模板中(我想我使用的是 C++ STL 词汇,对吧..?)。我有这个:

template<typename> class stSortOrder;
stSortOrder = std::less;
if(sortby == "descending")
    {
    stSortOrder = std::greater;
    }

显然它不能编译。我很确定这是因为我是 STL 的新手。


澄清:

我正在实施this thread(公共成员函数的变体)中接受的答案。

这是我希望避免在 switch 案例中重复的内容:

void CSubscriptionItem::sortMonitoredItems( int nColumnIndex, Qt::SortOrder ulOrder )
    {
    switch(nColumnIndex)
        {
        case CMonitoredItem::NAME:
            {
            if(ulOrder == Qt::DescendingOrder)
                {
                qSort(  m_qlpcMonitoredItems.begin(), 
                        m_qlpcMonitoredItems.end(), 
                        make_method_comparer<std::less>(&CMonitoredItem::getName) );
                }
            else
                {
                qSort(  m_qlpcMonitoredItems.begin(), 
                        m_qlpcMonitoredItems.end(), 
                        make_method_comparer<std::greater>(&CMonitoredItem::getName) );
                }
            break;
            }

我想用一个已经根据排序顺序参数设置的模板替换 make_method_comparer 中的 std::less 和 std::greater。这将真的有助于减少代码大小。

我已经考虑了发布的两个答案,但它们似乎不起作用 - 可能是因为我对模板不太熟悉,而且我只是不正确地使用它们。

【问题讨论】:

    标签: c++ templates sorting stl


    【解决方案1】:

    可以做到:

    template <typename T>
    struct comparer
    {
        comparer(bool is_less) : is_less(is_less) {}
    
        bool operator()(const T& x, const T& y) const
        {
            return is_less ? std::less<T>()(x, y) : std::greater<T>()(x, y);
        } 
    
    private:
        bool is_less;
    };
    

    但我宁愿这样做(更清楚):

    template <typename T>
    struct comparer
    {
        bool operator()(const T& a, const T& b) const
        {
            return is_less ? a < b : b < a;
        }
    
    private:
        bool is_less;
    };
    

    【讨论】:

    • 我很好奇为什么您的第一个示例会遇到定义联合的麻烦。将两个对象都定义为成员不是更容易吗?
    • @Mark:重点是澄清意图,不太重要的是,节省一些空间(在这方面更好的是能够从联合继承)。
    • lessgreater 应该是非常便宜的按需构建,所以为什么要与工会搞混。它们可能具有的一个优点是它们应该对指针进行专门化,即使它们没有指向同一个对象,也可以正确地比较它们。
    • @UncleBens:我完全同意,并且真的更喜欢第二种解决方案。但是,OP 似乎想在std::lessstd::greater 之间进行调度。让我提供一个更好的版本。
    • 我已经更新了我的问题。希望更清楚我在寻找什么。
    【解决方案2】:

    如果您的编译器支持 TR1,您可以:

    std::vector<int> v = { 3, 9, 17, 12, 5, 4 }; // NOTE: C++0x initialiser
    const bool ascending = true;
    typedef std::tr1::function<bool(int, int)> sort_func;
    sort_func& func = ascending
        ? static_cast<sort_func>(std::less<int>())
        : static_cast<sort_func>(std::greater<int>());
    std::sort(v.begin(), v.end(), func);
    

    或者,如果您有 boost,请将 std::tr1::function 替换为 boost::function

    【讨论】:

    • 比这复杂一点。看看我的说明:我正在使用模板来比较使用公共成员函数的对象。 那个模板也需要一个类模板,而不是一个函数。
    【解决方案3】:

    您将需要一个辅助类在运行时解决此问题,请执行以下操作:

    template <typename T>
    class ChosedSorter {
    public:
        ChosedSorted(bool descending) : _d(descending)
        {
        }
        bool operator()(const T& a, const T& b) {
            if( _d )
                return _less(a,b);
            return _greater(a,b);
        }
    private:
        bool _d;
        std::less<T> _less;
        std::greater<T> _greater;
    }
    

    然后你就这样使用它:

    void CSubscriptionItem::sortMonitoredItems( int nColumnIndex, Qt::SortOrder ulOrder )
        {
        switch(nColumnIndex)
            {
            case CMonitoredItem::NAME:
                {
                ChosedSorted<QString> sorter(ulOrder == Qt::DescendingOrder);
                    std::sort(  m_qlpcMonitoredItems.begin(), 
                            m_qlpcMonitoredItems.end(), 
                            sorter);
                break;
                }
    // ...
    

    【讨论】:

    • 次要的 nitpick,_d 可以在任何时候安全地读写,并且应该是公共/更好的名称,或者有一个 getter/setter。
    • @Mooing:为什么?谓词是一次性对象。您只需创建另一个而不是更改一个的状态。 - 但是为什么这个函子会存储lessgreater?也可以return std::less&lt;T&gt;()(a, b);
    • 我更喜欢保留一份副本,也许有人最终会专门化 std::less 并在构造函数中放入对排序很重要的东西......
    • 正如我在其他评论中所说,我已经更新了我的问题。希望更清楚我在寻找什么。
    • @UncleBens:但它不会重用相同的谓词。它将为每个operator() 调用构造一个新的谓词对象。
    猜你喜欢
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多