2015-11-09 43 views
5

std :: lower_bound() ve std :: upper_bound() sözdiziminde (iyi, tür dönüştürme) gerçekten bir tutarsızlık gibi görünen şeyleri gördünüz ve herhangi birinin açıklamasını isteyip istemediğini merak ettiniz mi? Yorumlara göre, satır 2, satır 1'e olan belirgin benzerliğine rağmen derlenmeyecektir; Eğer 3. hatta gösterilen formu kullanmaya gerek (en azından gcc üzerinde 4.7.3/ubuntu 64 bit - ben oynamak için bir tek bu var)upper_bound ve lower_bound tutarsız değer gereksinimleri

#include <set> 
#include <algorithm> 

using namespace std; 

class MyInt { 
    private: 
    int val; 
    public: 
    MyInt(int _val): val(_val) {} 
    bool operator<(const MyInt& other) const {return val < other.val;} 
}; 

int main() { 
    set<MyInt> s; 
    s.insert(1); // demonstrate implicit conversion works 
    s.insert(MyInt(2)); 
    s.insert(3); // one last one for the road 
    set<MyInt>::iterator itL = lower_bound(s.begin(), s.end(), 2); //LINE 1 
    // the line below will NOT compile 
    set<MyInt>::iterator itU = upper_bound(s.begin(), s.end(), 2); //LINE 2 
    // the line below WILL compile 
    set<MyInt>::iterator itU2 = upper_bound(s.begin(), s.end(), MyInt(2)); // LINE 3 
    return 0; 
} 
+0

G ++ 4.8.4 ile aynı davranış burada. Bu kesinlikle bir g ++ hatası. –

cevap

5

Ben bir hata olduğunu sanmıyorum. Eğer (possible) implementation of std::upper_bound bakarsak, çünkü karşılaştırma

if (!(value < *it)) { ... } // upper_bound, implicit conversion `MyInt`->`int` doesn't work 

gibi yapılır Ve operator< çünkü MyInt üyesi fonksiyonudur (ve bir sınıf türü değil int ait), kod derleme değil MyInt'dan int'a dönüştürme yoktur. Öte yandan, std::lower_bound, *it, *it, value (int türünde) MyInt::operator< geçirildiğinde örtük olarak MyInt dönüştürülebilir.

if (*it < value) { ... } // lower_bound, implicit conversion `int`->`MyInt` works 

Bu

üye olmayanlara olarak karşılaştırma operatörlerini uygulamak daha iyidir sebebi, bu yüzden bu asimetriyi yok. Bu ayrıca Scott Meyers'in Effective C++ kitabında da belirtilmiştir: Öğe 24: Tür dönüşümleri tüm parametrelerine uygulanacak olduğunda üye olmayan işlevleri bildirme.

hızlı ve kirli düzeltme: int örtülü dönüşüm MyInt bir MyInt::operator int(){return val;} tanımlar. (DÜZENLEME: gerçekten çalışmıyor, belirsizlik). Bunun yerine, örtük dönüştürme gereksinimini ortadan kaldırmaktır.

+0

iyi kazma, teşekkürler! STL uygulamasının (tartışmasız) arayüzünü karıştırması ilginçtir. Örtük tip dönüşümleri affethe için başka bir neden – aho

+0

@aho Evet, süper iyi bir sebep, büyük soru btw. 'Std :: upper_bound',' value' den '' '' 'a bir dönüşüm daha yaparsak ve bunu geçici olarak saklarsak muhtemelen "sabit" olabilir, ardından karşılaştırmadaki ikincisini kullanın. Bu durumda, davranış std :: lower_bound' ile tam olarak aynı olacaktır ve ödeme için bir fiyat yoktur (kodun derlenmesini istiyorsanız yine de ödersiniz). – vsoftco