2013-10-10 46 views
1

當我使用CRTP(Curiously recurring template pattern)時,當基類明確地可轉換爲bool,並且也可以轉換爲Derived類型時,出現編譯器錯誤。如果我嘗試使用ostream作爲右值輸出Derived類型,則會發生編譯器錯誤。例如:CRTP模糊過載

#include <iostream> 
    using namespace std; 

    template <class Object> 
    class Base 
    { 
     private: 

     typedef void (Base::*explicit_bool_type)() const; 

     void explicit_bool_idiom() const { } 

     public: 

     operator explicit_bool_type() const 
     { 
      return &Base::explicit_bool_idiom; 
     } 

     operator Object&() 
     { 
      return Object(); 
     } 

     operator const Object&() const 
     { 
      return Object(); 
     } 
    }; 

    class Derived : public Base<Derived> 
    { 
     public: 

     friend std::ostream& operator << (std::ostream& os, const Derived& d) 
     { 
      os << "abc"; 
      return os; 
     } 
    }; 

    int main() 
    { 
     std::cout << Derived() << std::endl; 
    } 

這使編譯器錯誤:

test2.cpp:42: error: ambiguous overload for ‘operator<<’ in ‘std::cout << Derived()’ 
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:102: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] 
test2.cpp:32: note:     std::ostream& operator<<(std::ostream&, const Derived&) 

問題:這是一個編譯器錯誤?我懷疑它可能是因爲它只發生在GCC的舊版本上,比如GCC 4.1.2。使用GCC 4.8.2,它工作正常。不幸的是,我需要讓它在較老的編譯器上工作。如果我將std::ostream& operator <<重載爲Derived,則可以使用。 (如果我輸出一個Derived作爲左值的實例,它也有效。)

我不確定爲什麼編譯器認爲std::ostream::operator << (bool)是一個同樣有效的候選人。另外,我知道顯式布爾成語已經與C++ 11過時了 - 再一次,需要讓這個工作在較老的編譯器上。

有沒有辦法解決模糊不超過std::ostream& operator <<Derived

回答

1

它確實看起來是g ++ 4.1中的一個bug。它至少在4.2.3及更高版本中起作用。

此外,如果您刪除隱式轉換爲explicit_bool_type或兩者都Object&轉換它編譯罰款。我強烈認爲隱式向下轉換是一個壞主意(假設你的實際實現並不真正通過引用返回一個棧變量),並建議刪除這些運算符,這樣做會增加修復編譯錯誤的好處。