2013-01-31 60 views
1

我已經定義了一個boost ::精神::齊規則:隱式轉換不起作用

boost::spirit::qi::rule<Iterator, Identifier()> id; 

其中標識符被定義爲:

BOOST_STRONG_TYPEDEF(std::string, Identifier) 

但是當我使用

BOOST_SPIRIT_DEBUG_NODE(id); 

無法編譯時出現以下錯誤:

boost_1_51_0/boost/spirit/home/support/attributes.hpp:1203: error: no match for 'operator<<' in 'out << val' 

它列出了ostream的重載操作符。

明知BOOST_STRONG_TYPEDEF定義轉換運算符原始類型,不應 編譯器標識符隱式轉換的std :: string使用operator<<什麼時候?或者是否存在限制,以防止編譯器在嘗試匹配其他運算符時應用類型的類型轉換運算符(即operator<<)?

當我定義下面的操作它編譯:

inline std::ostream& operator<<(std::ostream& os, const Identifier& id) 
{ 
    return os << static_cast<std::string const&>(id); 
} 

我使用gcc4.4.2

+1

當然,總是使'static_cast '。否則無意義的複製 – sehe

回答

4

這有沒有關係升壓,strong_typedef或精神。

它與模板參數的類型推演有很大關係。總之,當參數類型推導,隱式轉換從未走位[1]

參見:

#include <iostream> 
#include <string> 
#include <boost/strong_typedef.hpp> 

BOOST_STRONG_TYPEDEF(double, X) 
int main() { std::cout << X(); } 

沒問題!替換doublestd::string,它不再工作。有什麼不同?

流媒體運算符的聲明不同。

對比度

ostream& ostream::operator<<(double); 

template<typename _CharT, typename _Traits, typename _Alloc> 
    inline basic_ostream<_CharT, _Traits>& 
    operator<<(basic_ostream<_CharT, _Traits>&, basic_string<_CharT, _Traits, _Alloc> const&) 

事實上,運算符重載是函數模板不允許任何隱式轉換。


[1]我想initializer_list可能看起來好像有點例外的在這裏,有什麼用加寬/縮小,它可以做。不同的主題,雖然

+0

我發現與您提到的恕我直言相沖突的C++ 98標準中的一個例子。但我可能會誤解。請看http://nepsweb.co.uk/langstand/isoCPP/ISO14882/template.html。第14.8.3節示例4.子類型正在被轉換爲基本類型引用。問題是如果聲明「運算符重載是函數模板的事實不允許任何隱式轉換」。是真的,那麼爲什麼根據標準隱式轉換爲基礎引用類型是允許的? – amirmonshi

+0

@amirmonshi這不是演員。這只是對同一對象的多態引用(OO中的同一對象_identity_說) – sehe

+0

它不是稱爲upcast嗎?但我想我明白你的意思。運算符實際上是一種轉換,編譯器在推導模板類型時需要格外小心,但向基礎引用上傳到某種程度上是「自動」的。 – amirmonshi