![](/img/trans.png)
[英]Overloading operator<<: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
[英]Overloading operator<<: cannot bind lvalue to ‘std::basic_ostream<char>&&’
我有一個使用嵌套類的類,並希望使用嵌套類operator<<
operator<<
在上層類中定義operator<<
。 以下是我的代碼的樣子:
#include <memory>
#include <iostream>
template<typename T>
struct classA {
struct classB
{
template<typename U>
friend inline std::ostream& operator<< (std::ostream &out,
const typename classA<U>::classB &b);
};
classB root;
template<typename U>
friend std::ostream& operator<< (std::ostream &out,
const classA<U> &tree);
};
template<typename T>
inline std::ostream& operator<< (std::ostream &out,
const classA<T> &tree)
{
out << tree.root;
return out;
}
template<typename T>
inline std::ostream& operator<< (std::ostream &out,
const typename classA<T>::classB &b)
{
return out;
}
int main()
{
classA<int> a;
std::cout << a;
}
在不支持C ++ 11的情況下進行編譯時,編譯器似乎找不到內部類的operator <<的定義:
so.hpp:24:7: error: no match for 'operator<<' in 'out << tree.classA<int>::root' so.hpp:24:7: note: candidates are: ...
使用std = c ++ 0x進行編譯時使用GCC 4.6和4.7:
so.hpp:21:3: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' In file included from /usr/include/c++/4.7/iostream:40:0, from so.hpp:2: /usr/include/c++/4.7/ostream:600:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = classA<int>::classB]'
有人能告訴我為什么這段代碼不合法,什么是做我想要的最好的方法?
您在此運算符中遇到“不可導入的上下文”問題
template<typename T>
inline std::ostream& operator<< (std::ostream &out,
const typename classA<T>::classB &b)
{
return out;
}
編譯器無法確定哪個T
值會導致classB
與您要傳遞的參數匹配。 所以這個模板不予考慮!
在C ++ 11模式下,編譯器繼續從標准庫中找到一個緊密匹配
operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)
它可以匹配_Tp
幾乎任何類型,包括classA<T>::classB
,但注意第一個參數不匹配。
Bo提供了為什么會發生這種情況的原因 (類型T
在嵌套operator<<
的調用中是不可推斷的。這是一個簡單的解決方法,我推薦的一般情況,不僅僅是在這里,不是模板的朋友,而是而是一個單獨的自由函數。為此你需要定義內聯函數:
template<typename T>
struct classA {
struct classB
{
friend inline std::ostream& operator<< (std::ostream &out,
const classB &b) {
// definition goes here
}
};
classB root;
friend std::ostream& operator<< (std::ostream &out,
const classA<U> &tree) {
// definition goes here
}
};
這兩種方法有兩點不同。 最重要的一點是,這種方法將使編譯器為模板的每個實例化定義operator<<
的非模板化重載,因為它不再是模板,不依賴於推導參數。 另一個副作用是方法更緊湊 (你只是與一個函數交朋友,而在你最初的方法中,你結識了模板和所有可能的實例化(可以作為漏洞來獲得對你的類內部的訪問)。這樣定義的函數只能通過ADL找到,因此當參數不是ClassA<T>
或ClassA<T>::ClassB
時,編譯器要考慮的operator<<
重載次數較少。
如何通過您的方法獲得訪問權限
namespace {
struct intruder {
ClassA & ref;
intruder( ClassA& r ) : ref(r) {}
};
template <>
std::ostream& operator<< <intruder>( std::ostream& _, ClassA<intruder> const& i ) {
std::cout << i.ref.private_member << std::endl;
return _;
}
}
替代
或者,您可以與模板的特定專業化建立聯系。 這將解決intruder
問題,因為它只對operator<<
to ClassA<intruder>
,后者的影響要小得多。 但這不會解決您的特定問題,因為該類型仍然無法推斷。
試試這個:
template<typename T>
inline std::ostream& operator<< (std::ostream &out,
const classA<T> &tree)
{
//out << tree.root;
::operator<<( out, tree.root);
return out;
}
然后你會得到一個直率的無能告白:
test.cpp:34:3: error: no matching function for call to ‘operator<<(std::ostream&, const classA<int>::classB&)’
test.cpp:34:3: note: candidates are:
test.cpp:23:22: note: template<class T> std::ostream& operator<<(std::ostream&, const typename classA<T>::classB&)
test.cpp:30:22: note: template<class T> std::ostream& operator<<(std::ostream&, const classA<T>&)
解決方法:也許您可以在嵌套的classB中使用成員函數,並使用它而不是運算符<< ...當然,該解決方案有許多缺點,但它可能會讓您擺脫這種匆忙。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.