我想重載一個函數,以便它以某種方式操作它的參數,然後返回參數的引用 - 但是如果參數不可變,那麼它應該返回一個操縱的副本的參數代替。 經過一段時間的搞亂之後,這裏就是我想到的。rvalue函數重載
using namespace std;
string& foo(string &in)
{
in.insert(0, "hello ");
return in;
}
string foo(string &&in)
{
return move(foo(in));
}
string foo(const string& in)
{
return foo(string(in));
}
此代碼似乎能正常工作,但我很想聽聽有沒有人能想到更好的方法來做到這一點。
這是一個測試程序:
int main(void)
{
string var = "world";
const string var2 = "const world";
cout << foo(var) << endl;
cout << var << endl;
cout << foo(var2) << endl;
cout << var2 << endl;
cout << foo(var + " and " + var2) << endl;
return 0;
}
正確的輸出是
hello world
hello world
hello const world
const world
hello hello world and const world
我想這將是稍微整潔,如果我能做到這一點:
string& foo(string &in)
{
in.insert(0, "hello ");
return in;
}
string foo(string in)
{
return move(foo(in));
}
當然,這不起作用,因爲大多數對foo
的函數調用都是不明確的 - 包括01中的調用本身!但如果我能以某種方式告訴編譯器優先考慮第一個...
正如我所說的,我發佈的代碼工作正常。我不喜歡它的主要原因是重複的額外代碼。如果我有一堆這樣的功能,它會變得相當混亂,而且大部分都是非常重複的。作爲我的問題的第二部分:任何人都可以想出一種方法來自動生成第二個和第三個foo
函數的代碼?例如
// implementation of magic_function_overload_generator
// ???
string& foo(string &in);
magic_function_overload_generator<foo>;
string& bar(string &in);
magic_function_overload_generator<bar>;
// etc
這聽起來很可怕。根據我傳遞給函數的類型,返回值*和參數*的結果狀態可能完全不同。這只是要求微妙的錯誤。爲什麼不讓用戶決定是否要通過顯式調用不同的函數來修改對象或返回副本? – jalf 2011-06-16 08:05:09
對我來說這似乎並不特別可怕,但也許你是對的。我想到的方式是該功能在輸入時會改變輸入;但如果它不能......那麼它不會,但它仍然會給出正確的返回值。 我可能會使用它的一種東西就像是一個「標點符號」函數,它使用了一個不好打斷的字符串並對其進行修復。您可能希望將結果直接發送到cout,或者您可能想在之後對字符串執行一些其他操作。所以有時你可能會傳遞不變的價值觀,有時候......你明白了。 – karadoc 2011-06-16 08:26:07
但我的觀點是,無論是其中一個還是另一個發生都不取決於程序員想要什麼,而是取決於某些相對微妙的語義細節(參數類型是否爲const?是否是右值?),如果程序員沒有明確地做出「現在我想返回一個副本,而不是修改對象」的決定,它可能很容易隨時間而改變。我明白你想要做什麼,但這是程序員可以輕易做出的決定,以及在哪裏讓你的圖書館做出錯誤的猜測可能會有非常糟糕的後果。 – jalf 2011-06-16 08:32:35