Bu tür bir vector
veya herhangi bir başka uygulanabilir (değiştirilebilir giriş yineleyici) özel nesne türünün sıralanması X
, özellikle aşağıdaki gibi standart kütüphane algoritmalarının kullanılması dahil olmak üzere çeşitli yöntemler kullanılarak elde edilebilir.
Tekniklerin çoğu beri, göreli sipariş elde etmek X
öğelerin için zaten gönderildiğinden, çeşitli yaklaşımları kullanmak için "neden" ve "ne zaman" ile ilgili bazı notlar ile başlayacağım.
"En iyi" yaklaşım farklı faktörlere bağlı olacaktır:
X
Nesnelerin aralıklarını sıralamak yaygın veya nadir bir görev midir (bu aralıklar programda veya kütüphane kullanıcıları tarafından farklı yerlerde sıralanacaktır)?
- Gerekli sıralama "doğal" mı (beklenen) veya türün kendisiyle karşılaştırılabilecek birden fazla yolu var mı?
- Performans bir sorun mudur yoksa
X
nesne sıralaması kusursuz mu olmalıdır?
Sıralama aralıkları X
ortak bir görevse ve elde edilen sıralama beklenirse (yani X
yalnızca tek bir temel değeri sararsa), muhtemelen aşırı yüklenmeye gideroperator<
sararsa), herhangi bir fuzz olmadan (uygun karşılaştırıcıları doğru bir şekilde geçirme gibi) sıralama ve tekrarlanan beklenen verim sağladığı devam eder. Sonuçlar.
Sıralama ortak bir görevse veya farklı bağlamlarda gerekli olması gerekiyorsa, ancak X
nesneleri sıralamak için kullanılabilecek birden fazla ölçüt varsa, Functors ( operator()
özel sınıfların aşırı yüklenmiş işlevleri) veya işlev işaretçileri (yani bir functor / işlevi) sözcüksel sıralama için ve diğeri doğal sıralama için).
Tür sıralama aralıkları X
nadir veya diğer bağlamlarda olası değilse , daha fazla işlev veya türle herhangi bir ad alanını karıştırmak yerine lambdaları kullanma eğilimindeyim.
Bu, sıralama bir şekilde "açık" veya "doğal" değilse özellikle doğrudur. Yerinde uygulanan bir operator<
lambdaya bakarken mantığı siparişin arkasına kolayca alabilirsiniz, oysa ilk bakışta opague ve hangi sipariş mantığının uygulanacağını bilmek için tanımına bakmanız gerekir.
Bununla birlikte, tek bir operator<
tanımın tek bir hata noktası olduğunu, ancak birden çok lambanın birden çok hata noktası olduğunu ve daha fazla dikkat gerektirdiğini unutmayın.
Eğer tanımı operator<
sıralama sıralama şablon derlenmiş / yapıldığı yerle ilgili kullanılamaz, derleyici nesneleri karşılaştırarak, yerine ne zaman en azından ciddi bir dezavantaj olabilir sipariş mantığı (inlining zaman bir işlev çağrısı yapmak zorunda kalabileceğini bağlantı zamanı optimizasyonu / kod oluşturma uygulanmaz).
class X
Standart kütüphane sıralama algoritmalarını kullanarak karşılaştırılabilirlik elde etmenin yolları
Bırakın std::vector<X> vec_X;
vestd::vector<Y> vec_Y;
1. Karşılaştırma işlevi beklemeyen standart kitaplık şablonlarını aşırı yükleyin T::operator<(T)
veya operator<(T, T)
kullanın.
Her iki aşırı yük üyesi operator<
:
struct X {
int i{};
bool operator<(X const &r) const { return i < r.i; }
};
// ...
std::sort(vec_X.begin(), vec_X.end());
veya ücretsiz operator<
:
struct Y {
int j{};
};
bool operator<(Y const &l, Y const &r) { return l.j < r.j; }
// ...
std::sort(vec_Y.begin(), vec_Y.end());
2. Sıralama işlevi parametresi olarak özel bir karşılaştırma işlevine sahip bir işlev işaretçisi kullanın.
struct X {
int i{};
};
bool X_less(X const &l, X const &r) { return l.i < r.i; }
// ...
std::sort(vec_X.begin(), vec_X.end(), &X_less);
3. bool operator()(T, T)
Karşılaştırma işlevi olarak geçirilebilen özel bir tür için bir aşırı yük oluşturun .
struct X {
int i{};
int j{};
};
struct less_X_i
{
bool operator()(X const &l, X const &r) const { return l.i < r.i; }
};
struct less_X_j
{
bool operator()(X const &l, X const &r) const { return l.j < r.j; }
};
// sort by i
std::sort(vec_X.begin(), vec_X.end(), less_X_i{});
// or sort by j
std::sort(vec_X.begin(), vec_X.end(), less_X_j{});
Bu işlev nesnesi tanımları C ++ 11 ve şablonlar kullanılarak biraz daha genel olarak yazılabilir:
struct less_i
{
template<class T, class U>
bool operator()(T&& l, U&& r) const { return std::forward<T>(l).i < std::forward<U>(r).i; }
};
üye i
destekli herhangi bir türü sıralamak için kullanılabilir <
.
4. Sıralama işlevlerine karşılaştırma parametresi olarak bir anonim kapanışı (lambda) geçirin.
struct X {
int i{}, j{};
};
std::sort(vec_X.begin(), vec_X.end(), [](X const &l, X const &r) { return l.i < r.i; });
C ++ 14 daha da genel bir lambda ifadesini mümkün kılıyorsa:
std::sort(a.begin(), a.end(), [](auto && l, auto && r) { return l.i < r.i; });
bir makroya sarılabilen
#define COMPARATOR(code) [](auto && l, auto && r) -> bool { return code ; }
sıradan karşılaştırıcı oluşturma işlemini oldukça pürüzsüz hale getirir:
// sort by i
std::sort(v.begin(), v.end(), COMPARATOR(l.i < r.i));
// sort by j
std::sort(v.begin(), v.end(), COMPARATOR(l.j < r.j));