2012-08-17 57 views
15

我想寫一個模板函數,它接受2個值和一個函子或一個lambda。 函數使用這些值調用函數並返回結果。如何推斷函子返回值的類型?

template <typename T, typename Fn> 
_ReturnTypeOfPred_ Apply(T x, T y, Fn fn) 
    { 
    return fn(x, y); 
    } 

問:我如何定義的Apply返回類型成爲等於Fn返回類型?它不一定等於T,如仿

template <typename T> 
auto Sum(T x, T y) -> decltype(x+y) 
    { 
    return x+y; 
    } 

更新

首屆例子是過於簡單化的這個例子。 這個應該工作嗎?

template <typename TContainer, typename Fn> 
auto Apply(const TContainer& x, const TContainer& y, Fn fn) -> decltype(fn(x.front(), y.front())) 
    { 
    return fn(x.front(), y.front()); 
    } 

想如果我在返回類型的decltype重複return表達它總是工作?有沒有更優雅的方式?

+2

下劃線的大寫名稱保留用於實施。你不能在你自己的代碼中使用它們。 – 2012-08-17 12:32:46

+2

@KerrekSB:它是一個佔位符,不是一個真實的代碼 – Andrey 2012-08-17 12:34:08

+0

好的函子(比如那些在STL中的)總是定義它們的'return_type',所以你可以使用'Fn :: return_type'。但我知道你想要一個也適用於不那麼好的函數的答案。 – Gorpik 2012-08-17 12:34:34

回答

18

你快到了;只需使用decltype

template <typename T, typename Fn> 
auto Apply(T x, T y, Fn fn) -> decltype(fn(x, y)) 
{ 
    return fn(x, y); 
} 

你可以使用std::result_ofDifference between std::result_of and decltype),但何必呢?

template <typename T, typename Fn> 
typename std::result_of<Fn, T, T>::type Apply(T x, T y, Fn fn) 
{ 
    return fn(x, y); 
} 

關於後續問題:一個函數

auto fn(<args>) -> <return-type> { return <expression>; } 

decltype(<expression>)通常工作代return-type,但也很容易出錯。例如,考慮:

auto f(char c) -> decltype(std::string() += c) { return std::string() += c; } 

這裏decltype將產生std::string &和你的函數會返回一個左值引用到本地!這將具有將被改變到:

auto f(char c) -> std::remove_reference<decltype(std::string() += c)>::type { 
    return std::string() += c; 
} 

在其他情況下,<expression>可以產生一個值,該值是不退還對於由於成爲例如不可複製,包含拉姆達等。

+0

謝謝,你能看看最新的問題嗎? – Andrey 2012-08-17 12:35:40

+0

@Andrey見上文。 – ecatmur 2012-08-17 12:52:06

+0

您鏈接的問題並沒有強調'std :: result_of'和'decltype'之間的區別。出於OP的目的,'std :: result_of'不合適。 – 2012-08-18 01:35:29

相關問題