2015-07-15 11 views
6

jestem napotyka błąd kompilacji za pomocą następującego kodu:zdefiniowany przez użytkownika funkcja konwersji i oddające odwołać

class SymbolGroup 
{ 
    std::string d_; 

public: 
    SymbolGroup(std::string a):d_(a){} 

    // explicit operator const std::string&() const { return d_;} // compiles 
    explicit operator std::string() const { return d_;} // Does not compile 
}; 

inline 
bool operator==(const SymbolGroup& lhs, const SymbolGroup& rhs) 
{ 
    return static_cast<const std::string&>(lhs) == 
    static_cast<const std::string&>(rhs); 
} 

int main(){ 

    SymbolGroup a("hello"); 
    SymbolGroup b("hello"); 

    if (a==b) 
    std::cout << "they are the same\n"; 

    return 0; 
} 

Bez „const” i „&” w wierszu konwersji zdefiniowanej przez użytkownika typ, robi nie wkompilowania g ++ (4.8) z --std = C++ 11 flag

error: invalid initialization of reference of type ‘std::string& {aka std::basic_string&}’ from expression of type ‘const string {aka const std::basic_string}’ explicit operator std::string&() const { return d_;}

Kod zestawia na Clang obie strony. Który kompilator jest poprawny? Czy ten kod powinien się kompilować z operator std::string()?

+0

otrzymuję [no Błąd kompilacji] (http://cpp.sh/6wbj) – CoryKramer

+1

@CoryKramer Czy kompilacji przy użyciu wersji bez 'const' i '&'? – ENIGMA

+1

Wystarczy FYI - jeśli masz pytania o kod nie kompilacji, to lepiej napisać przykład jako kod, który nie kompiluje tak, że ludzie mogą po prostu szybko skopiować i wkleić. – Barry

Odpowiedz

4

UPDATE Moja poprzednia odpowiedź była dokładnie źle . Przeprosiny! tldr; clang jest poprawny, aby zaakceptować kod, gcc jest niepoprawny, aby go odrzucić.


pierwsze, z [expr.static.cast]:

An expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e) ; is well-formed, for some invented temporary variable t (8.5).

Tak skutecznie staramy się kierować zainicjować obiektu typu std::string const& wyraźnie od obiektu typu SymbolGroup const&. Jest sekcja specjalnie na inicjowanie referencji przez funkcję konwersji: „Zainicjowanie przez funkcję konwersji do wiązania bezpośredniego odniesienia” [over.match.ref]:

Under the conditions specified in 8.5.3, a reference can be bound directly to a glvalue or class prvalue that is the result of applying a conversion function to an initializer expression. Overload resolution is used to select the conversion function to be invoked. Assuming that “cv1 T” is the underlying type of the reference being initialized, and “cv S” is the type of the initializer expression, with S a class type, the candidate functions are selected as follows:

— The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that [...] are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within S and yield type “lvalue reference to cv2 T2” or “cv2 T2” or “rvalue reference to cv2 T2”, respectively, where T2 is the same type as T or can be converted to type T with a qualification conversion (4.4), are also candidate functions.

Pierwsza część nie ma zastosowania, ponieważ nasza funkcja konwersji explicit, więc go pominąłem. Druga część ma. Mamy cv1 T jest const std::string, więc nasza funkcja konwersji na std::string jest funkcją kandydującą, ponieważ std::string można przekonwertować na const std::string z konwersją kwalifikacji.


gcc jest tu źle, a ja złożony bug 66893, potwierdzony przez nasz własny C++ ekspert i wszystko wokół dobry facet Jonathan Wakely jak również głowy dzyń dewelopera i C++ standardowy edytor Richard Smith (po tym, jak dokładnie zakłopotany się złożenie błąd Clang).

1

Dobrze panie, odpowiedź i całkiem proste. Zamiast rzucania do const odniesienia w zamian jak ten:

return static_cast<const std::string&>(lhs) == static_cast<const std::string&>(rhs); 

Oddaj swój typ na std::string:

return static_cast<std::string>(lhs) == static_cast<std::string>(rhs); 

I cieszyć działający kod :)

+1

To nie odpowiada na pytanie. Ponadto OP chce uniknąć kopiowania ciągów. – Barry

+1

Chodzi o to '(const std :: string &) (lewa oś) == (const std :: string &) (prawa oś);' 'kompiluje i static_cast (lewa oś) == static_cast (rhs); 'does not. Czy ta różnica jest podana w standardzie? – dewaffled

+0

AFAIK użyciu c stylu obsady jest niebezpieczne w C++, ponieważ sprawia, że ​​kompilator wybrać sposób obsadzie sama.Dzięki temu może jednocześnie wykonywać rzuty statyczne, const i reinterpret. Być może w twoim przykładzie używa on statycznej i stałej obsady razem – bartop

Powiązane problemy