簡體   English   中英

C ++覆蓋特定數據類型的std :: set的默認小於參數

[英]C++ overriding default less than argument for std::set for a particular data type

我有很多代碼可以創建std::set<Port*> 現在默認情況下,它使用less<Port*>對指針值的集合進行排序。 這會在我們的工具中產生問題。 我想為所有set<Port*>提供一個默認的比較器my_less ,而不必去更改所有代碼。 所以我嘗試了模板專業化:

namespace std {
    template<> class set<Port*> : public set<Port*, my_less> {};
};

我將此代碼放在所有代碼文件中已經包含的頭文件中。 這與我預期的所有set<Port*>現在都使用my_less 問題是這種專業化不是繼承構造函數。 所以如果我想這樣做,我會收到一個錯誤:

std::set<Port*> myset_new(myset1.begin(), myset1.end());

set.cpp:53:63: error: no matching function for call to
‘std::set<Port*>::set(std::set<Port*, znl_id_less>::iterator, std::set<Port*, my_less>::iterator)’
    set_include.h:27:70: note: candidates are: std::set<Port*>::set()
    set_include.h:27:70: note:                 std::set<Port*>::set(const std::set<Port*>&)

什么是解決這個問題的好方法(我可以復制構造函數的代碼,但看起來並不干凈)。

除了:

template<> class set<Port*> : public set<Port*, my_less> {};

從 C++11 開始,您可以使用 using-declaration輕松繼承構造函數,如下所示:

namespace std {
    template<> class set<Port*> : public set<Port*, my_less> {
        public: using set<Port*, my_less>::set;
    };
};

這是我對這個問題的通用解決方案

#include <set>
#include <functional>
#include <iostream>

// structs
struct my_struct
{
    int a;
    int b;
};

struct my_second_struct
{
    int a;
    int b;
};

bool operator<(const my_second_struct& m1, const my_second_struct& m2)
{
    return m1.b < m2.b;
}

// alias helper
template <typename T>
using custom_comparator_t = std::function<bool(const T, const T)>;

// function to proxy already defined operator to pointers
template<typename T>
auto get_pointer_less()
{
    return [](const T* v1, const T* v2) -> bool { return (*v1) < (*v2); };
}

// this is generic solution
template<typename T>
using pointer_set = std::set<T*, custom_comparator_t<T*>>;

// and final config
template<typename T>
auto get_pointer_set()
{
    return pointer_set<T>( get_pointer_less<T>() );
}

template<typename T, typename _T>
void fill_and_display(_T& s)
{
    s.insert(new T{10, 20});
    s.insert(new T{20, 10});
    s.insert(new T{0, 100});
    s.insert(new T{100, 0});

    std::cout << "set: ";
    for (const T *ms : s)
        std::cout << "( " << ms->a << " ; " << ms->b << " )";
    std::cout << std::endl;
}

int main()
{
    // First option, create custom less operator inline
    std::set<my_struct *, custom_comparator_t<my_struct *>> myset(
        [](const my_struct *ms1, const my_struct *ms2) { return ms1->a < ms2->a; }
    );

    fill_and_display<my_struct>(myset);

    // Second option, reuse, already defined less operator
    std::set<my_second_struct *, custom_comparator_t<my_second_struct*>> my_second_set(
        get_pointer_less<my_second_struct>()
    );

    fill_and_display<my_second_struct>(my_second_set);

    // generic colution for second set
    auto my_third_set = get_pointer_set<my_second_struct>();

    fill_and_display<my_second_struct>(my_third_set);

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM