![](/img/trans.png)
[英]Why does the C++ standard not change std::set to use std::less<> as its default template argument?
[英]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.