[英]How can I resolve this address of overloaded member function issue?
[ 編輯 -我很早就忘記了這里,直到我得到2500個視圖的“顯着問題”。 由於人們正在查看-在接受的答案中有關於重載的有用信息,但特別是檢查std::endl
情況甚至比我當時意識到的還要糟糕,這肯定是錯誤的事情。
基本上, std::endl
的作用是將\\n
輸出到流中,然后使用std::flush
。 這與平台無關,包括Windows,其行尾實際上是“ \\ r \\ n”。 endl
操縱器並沒有抽象出WRT行末端的平台差異,C ++處理C的方式與之相同-稍后將\\n
轉換為“ \\ r \\ n”(對於文本模式,不是二進制)。 我以為C ++會做一些不同的事情,這個假設是如此強烈,以至於20年來我從未質疑過它,但是我錯了。
我不記得詳細信息,但是仍然可以定義自己的流,並提供流輸入的任何字符的替代輸出(和翻譯)。 在您的自定義流代碼看到生成的輸出字符之前 ,所有操縱器都應按預期工作。 因此,要提供特殊的行尾行為,請注意其中的\\n
(仍在文本文件行尾翻譯之前)。 ]
我知道這很棘手,但是最近我需要實現一個流類,該流類的行為基本上像是標准流,但是可以檢測到std :: endl操縱器,並在特殊情況下可以檢測其行為。 我對特定方法實現的首次嘗試是...
mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
if (p == &std::endl)
{
// Handle special case
}
else
{
m_Underlying_Stream << p;
}
return *this;
}
麻煩的是,編譯器不知道我指的是std::endl
重載。 我如下解決了...
mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);
const ENDL_T l_ENDL (&std::endl);
if (p == l_ENDL)
{
// Handle special case
}
else
{
m_Underlying_Stream << p;
}
return *this;
}
也就是說,編譯器可以在初始化的上下文中解決重載(並且也可以進行賦值,正如另一個實驗證明的那樣),但對於operator==
不能。
有問題的編譯器是MinGW GCC 4.4.0,但我認為這可能不是編譯器問題。
我環顧四周,發現了這個問題...
如果我的代碼有一個const問題,我不知道丟失的const需要去哪里。 我看不到其他明顯的類型問題。
我對WRT重載或隱式轉換的步數問題有一些模糊的想法,但是沒有具體的想法。 所以-任何人都可以清楚地說明我的第一個示例有什么問題,為什么第二個版本可以解決它,以及在使用函數地址時我如何可以安全地指出我的意思是哪個重載。
順便說一句-我猜有些人可能不喜歡我直接測試std::endl
的地址,並且會指出這很脆弱-例如某人可以擁有自己的操縱器,調用std::endl
,而我不會點。 總的來說,這是對的,但是在這種特殊情況下,hack可以節省很多時間,而無關緊要。
僅在有限的上下文集合中允許使用不帶參數的重載函數名稱(或行為類似於一組重載函數的函數模板的名稱)(例如在“ address of”表達式中)可用於唯一確定所需的特定過載。
這是在標准(ISO / IEC 14882:2003)[over.over]的13.4中指定的。 包括用於對象或引用或顯式轉換的初始化器。 這給您許多選擇。
例如顯式轉換:
typedef std::ostream& (*ManipPtr)(std::ostream&);
mystream& mystream::operator<<(ManipPtr p)
{
if (p == static_cast<ManipPtr>(&std::endl))
{
// ...
直接初始化指針:
typedef std::ostream& (*ManipPtr)(std::ostream&);
mystream& mystream::operator<<(ManipPtr p)
{
const ManipPtr pEndl = &std::endl;
if (p == pEndl)
{
// ...
以下作品:
#include <iostream>
struct mystream {
typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);
mystream& operator<< (ENDL_T p)
{
if (p == (ENDL_T)std::endl)
{
std::cout << "special case\n";
}
else
{
std::cout << "usual case\n";
}
return *this;
}
};
int main()
{
mystream ms;
ms << std::endl; // prints "special case"
ms << std::flush; // prints "usual case"
}
它無法區分重載的原因是因為您正在解析函數的地址,而不是調用它。 當您將其插入流中時,編譯器就會知道調用endl(ostream&)
重載。 除此之外,您是一個人。
為什么不只測試'\\ n'呢?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.