2013-07-14 80 views
21

有沒有辦法在C++中編寫一個接受左值和右值參數的函數,而不必將其作爲模板?同時接受左值和右值參數的函數

例如,假設我編寫了一個函數print_stream,該函數從istream中讀取並打印讀取到屏幕上的數據或其他內容。

我認爲這是合理的調用print_stream這樣的:

fstream file{"filename"}; 
print_stream(file); 

以及像這樣:

print_stream(fstream{"filename"}); 

但我怎麼聲明print_stream這樣既利用工作?

如果我聲明爲

void print_stream(istream& is); 

然後第二使用不能編譯,因爲右值將不結合到一個非const左值參考。

如果我聲明爲

void print_stream(istream&& is); 

然後在第一次使用不能編譯,因爲左值將不結合到一個rvalue參考。

我若爲

void print_stream(const istream& is); 

那麼函數的實現不能編譯,因爲你不能從一個const istream讀取。

我不能將該函數作爲模板並使用「通用引用」,因爲它的實現需要單獨編譯。

我公司可提供兩個重載:

void print_stream(istream& is); 
void print_stream(istream&& is); 

,並有第二個呼叫第一個,但好像很多不必要的樣板,我會覺得很不幸有這樣做,我每一次用這樣的語義編寫一個函數。

有什麼更好的我可以做嗎?

+0

你可以使用void print_stream(Wrapper)並將問題移動到Wrapper的構造函數,這隻有在你想對幾個函數執行相同時纔有意義。 –

+2

「每次我用這樣的語義編寫函數」?您是否經常編寫需要採用非常量非可複製參數的函數,並且必須使用臨時參數和左值參數來調用函數?這是一個非常具體的例子,而不是我擔心的「每次我必須用這樣的語義編寫函數」。如果參數是可複製的,您可以簡單地通過值來傳遞它。如果你不需要調用非const函數,你可以通過const引用 – jalf

+2

傳遞你可以寫一個幫手腳本'template T&stay(T && t){return t; }'並使用'stay(fstream {「filename」})''。 –

回答

15

除了提供兩個重載或將您的函數作爲模板之外,沒有太多的理智選擇。

如果你真的,真的需要一個(醜陋的)替代,那麼我想唯一的(瘋狂)的事情你可以做的是讓你的函數接受const&,有一個先決條件說,你不能傳遞一個一個const限定類型的對象(無論如何你都不想支持)。該功能將被允許丟棄參考的const

但我個人寫兩個重載和定義一個在其他方面,所以你做重複的聲明,但沒有定義:

void foo(X& x) 
{ 
    // Here goes the stuff... 
} 

void foo(X&& x) { foo(x); } 
+1

這不能很好地擴展(例如3個參數 - > 8個功能需要)。有沒有辦法解決這個問題?我與OP的位置大致相同。 – Dave

+1

@Dave會這樣的工作爲你的用例? http://coliru.stacked-crooked.com/a/e93ea8c3b693b593 – Mysticial

+0

@Mysticial這是一個非常整潔的解決方法,但不幸的是,3年後,我完全忘記了我需要的東西。如果它再次出現,我會記住它! – Dave

4

另一種比較難看的替代是使功能並明確地實例化兩個版本:

template<typename T> 
void print(T&&) { /* ... */ } 

template void print<istream&>(istream&); 
template void print<istream&&>(istream&&); 

這可以單獨編譯。客戶端代碼只需要模板的聲明。不過,我個人只是堅持Andy Prowl的建議。

+0

@ HighCommander4 [適用於我]。(http://coliru.stacked-crooked.com/view?id=fa0857865f55a2615158e93e8ceb5a76-3725be9f9ce62f113fc473b4ae69c419) – jrok

相關問題