C 11 std::lambda karşılaştırma işlevi ayarlayın
std::set
özel bir karşılaştırma ile bir fonksiyon oluşturmak istiyorum. Elimden tanımlamak gibi bir sınıf ile operator()
, ama ben istediğim için zevk yeteneği tanımlamak için bir lambda nerede kullanılır, bu yüzden karar verdim tanımlamak için lambda fonksiyonu başlatma listesi kurucu sınıfı olan std::set
gibi bir üye. Ama lambda tipi alamıyorum. Ben devam etmeden önce, burada bir örnek:
class Foo
{
private:
std::set<int, /*???*/> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
Arama yaptıktan sonra iki çözüm buldum:, std::function
kullanarak. Tam olarak benim yaptığım gibi sadece karşılaştırma işlevi türü std::function<bool (int, int)>
ve lambda geçişi var. İkinci çözüm make_set fonksiyon std::make_pair
gibi yazmaktır.
ÇÖZÜM 1:
class Foo
{
private:
std::set<int, std::function<bool (int, int)> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
ÇÖZÜM 2:
template <class Key, class Compare>
std::set<Key, Compare> make_set (Compare compare)
{
return std::set<Key, Compare> (compare);
}
Soru bir çözümü tercih etmek için iyi bir nedenim var mı? Standart özellikler (make_set standart bir fonksiyon değildir) kullanır, çünkü ilkini tercih ediyorum, ama merak ediyorum: std::function
Bu kod (potansiyel olarak) yavaş olun? kullanarak yapar Demek istediğim düşük şansı derleyici inlines karşılaştırma işlevi, ya da olması gerektiği kadar akıllı uslu aynen eskisi gibi olur bir lambda fonksiyonu yazın ve std::function
(biliyorum, bu durumda olamaz lambda tipi, ama biliyorsun, ben soruyorum genel) ?
(GCC kullanıyorum, ama popüler Derleyiciler genel olarak ne olduğunu bilmek istiyorum)
BÜYÜK BİR SÜRÜ CEVAP ALDIM SONRA ÖZETİ:
Eğer hız önemliyse en iyi çözüm operator()
aka functor bir sınıf kullanmaktır. Derleyici optimize etmek ve herhangi bir indirections önlemek için çok kolay.
Kolay bakım ve genel amaçlı bir çözüm daha iyi, C 11 özellikleri kullanarak için kullanın std::function
. Hala hızlı (biraz eşleme daha yavaş, ama önemsiz de olabilir) ve herhangi bir fonksiyon kullanabilirsiniz std::function
, lambda, herhangi bir nesne çağrılabilir.
Ayrıca, bir işlev işaretçisi kullanmak için bir seçenek var, ama eğer hız sorunu varsa yok std::function
daha iyi eğer C 11 kullanırsanız () olduğunu düşünüyorum.
Orada bir seçenek tanımlamak için lambda işlevi, başka bir yerde, ama o zaman kazanırsınız yoktan karşılaştırma işlevi olmak bir lambda ifadesi bu yana, mümkün olduğu kadar iyi bir sınıf ile operator()
konumu ve tanımı olmaz set inşaat zaten.
Daha fazla fikir, temsilci kullanma gibi. Eğer tüm çözümleri daha detaylı bir açıklama istiyorsanız, cevapları okuyun :)
CEVAP
Evet, bir std::function
sizin için neredeyse kaçınılmaz yönlendirme set
tanıttı. Süre derleyici her zaman, teorik olarak, anlamaya tüm kullanım set
std::function
içerir çağıran bir lambda yani hep aynı lambda, yani her ikisi de zor ve son derece kırılgan.
Kırılgan, çünkü daha önce derleyici kanıtlamak için kendisini tüm aramalar için std::function
* aslında bir çağrı için lambda, gerek ispat eden herhangi bir erişim için std::set
hiç ayarlar std::function
bir şey ama lambda. Tüm derleme birimleri std::set
ulaşmak ve hiçbiri bunu kanıtlamak için mümkün olan tüm yolları bulmak demektir.
Bu bazı durumlarda mümkün olabilir, ama nispeten zararsız değişirse derleyici bunu kanıtlamak için yönetilen varsa bile onu kırmak.
Öte yandan, vatansız operator()
ile bir functor kolay davranış kanıtlamak zorunda, ve bu iyileştirmeleri içeren günlük şeyler.
Yani Evet, pratikte std::function
daha yavaş olabilir şüpheli olurdu. Diğer taraftan, std::function
çözüm make_set
bir daha korumak için daha kolay ve program performansı için programcı zaman alışverişi oldukça görecelidir.
make_set
herhangi bir tür 33**'nın tip 34* *çağrı olayla olmalı. ciddi dezavantajı var Sık sık set
depolar kalıcı bir devlet ve oluşturduğunuz bir şey değil o zaman kapsam dışına düşmesine izin yığını.
Eğer oluşturduğunuz bir statik veya global vatansız lambda auto MyComp = [](A const&, A const&)->bool { ... }
kullanabilirsiniz std::set<A, decltype(MyComp)>
sözdizimi oluşturma set
Bu ısrar, henüz kolay derleyici için optimize (çünkü tüm örnekleri decltype(MyComp)
vatansız funktorlar) ve satır içi. struct
set
sokuyorsun çünkü ben, bu işaret etmektedir. (Veya derleyici destekler
struct Foo {
auto mySet = make_set<int>([](int l, int r){ return l<r; });
};
ben şaşırtıcı bulur!)
Son olarak, eğer sen are endişeli hakkında performans, düşünün std::unordered_set
çok daha hızlı (maliyet alamamak için üzerinde yineleme içeriği için, ve yazmak/bulmak iyi karma), ve bir sıralanmış std::vector
daha da varsa ve 2-faz "Ekle her şey" sonra "sorgu içeriğini tekrar tekrar". Sadece vector
ilk içine şeyler, 46* unique
erase
*, equal_range
ücretsiz algoritması kullanın.
Durum oluşturduğunda 8 Lambda işlevi, ...
Verimli tamsayı karşılaştırma işlevi...
(Lambda) kapatma Python yakalama işlev...
Neden Lambda daha düz fonksiyonları da...
Duyarlı Dize Karşılaştırma için SQL Du...