2015-02-01 12 views
7

0, bazı kapsayıcı kapsayıcıların (std :: set gibi) öğelerini bir kapsayıcıda depolananlardan başka türlerle karşılaştırmanıza izin verilir. Karşılaştırıcı, tür olarak belirtilen is_transparent olduğunda çalışmalıdır (bkz. Ör. std::set::find).Karşılaştırıcıyı is_transparent türüyle nasıl kullanırım? C++ 14 ile

Dize üzerinde bazı denetimler gerçekleştiren bir dize sarıcısına sahip olduğumu varsayalım (format geçerli bir biçime benziyorsa ve böyle devam ediyorsa) - gerçekten önemli değil, ancak bunu oluşturmak, onu önlemek isterim. istisnalar) ve std :: setinde benzersiz değerlerde bir konteynere sahip olacak şekilde saklanır. Bunun için nasıl bir karşılaştırıcı yazmalıyım? Aşağıdakine benziyor mu? Aynı şeyi elde etmek için sw::operator<()'u aşırı yükleyebilir ve kullanabilir miyim?

class sw 
{ 
public: 
    explicit sw(const std::string& s) : s_(s) { /* dragons be here */ } 
    const std::string& getString() const { return s_; } 

    bool operator<(const sw& other) const { return s_ < other.s_; } 

private: 
    std::string s_; 
}; 

struct Comparator 
{ 
    using is_transparent = std::true_type; 

    bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; } 
    bool operator()(const std::string& lhs, const sw& rhs) const { return lhs < rhs.getString(); } 
    bool operator()(const sw& lhs, const sw& rhs) const { return lhs < rhs; } 
}; 

int main() 
{ 
    std::set<sw, Comparator> swSet{ sw{"A"}, sw{"B"}, sw{"C"} }; 
    std::cout << std::boolalpha << (swSet.find(std::string("A")) != swSet.end()) << std::endl; 
} 

Yukarıdaki kod beklendiği gibi çalışması gerekir inanıyoruz ama g ++ 4.9 ve clang ++ 3.6 ile test edildiğinde, her iki Comparator::operator() dize aşırı yükler gibi eğer key_type için string dönüşümü eksik hakkında hataları vermiştir asla dikkate alınmadı. Bir şey mi eksik?

+4

libstdc sürümü ++:

inline bool operator<(const sw& lhs, const std::string& rhs) { return lhs.getString() < rhs; } inline bool operator<(const std::string& lhs, const sw& rhs) { return lhs < rhs.getString(); } std::set<sw, std::less<>> swSet{ sw{"A"}, sw{"B"}, sw{"C"} }; 

Ayrıca, sen bunlardan birini onun tanımına aynı etkiye sahip olacaktır için is_transparent tanımladığımız önemli değil belirterek muhtemelen değer g ++ 4.9 ile gelen gcc'nin standart kütüphanesi, heterojen bir arama gerçekleştirmemiştir. Kodunuz [clang ve libC++ ile iyi derler] (http://coliru.stacked-crooked.com/a/97c0421099d7912d). –

+0

@ T.C .: teşekkürler, bu mantıklı ve korktuğum şey ... Ben clang ve -stdlib = libC++ ile denedim ve amaçlandığı gibi çalıştı. Benim varsayılan ortam g ++ ve libstdC++ olduğunu çok kötü. –

+4

https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=219888 adresinde iki haftadan kısa bir süre önce uygulandı. –

cevap

3

Evet, bu kodun doğru, ama std::string ile türünü karşılaştıran izin operator< aşırı basit olabilir ve sadece zaten "saydam" olan std::less<> (yani std::less<void>) kullanacaktır. (

using is_transparent = std::false_type; 

using is_transparent = void; 
+0

Huh, daha az 've onun davranışını bilmiyordum, bu güzel. Yine de, böyle şeyler yaparken, ayrı bir karşılaştırıcı temizleyici ve daha etkileyici buluyorum, ama bu muhtemelen kişisel bir tercih. :) –

İlgili konular