2015-05-19 52 views
0

我正在試圖找出非成員函數的返回類型。我首先想到std::result_of完成了這項工作,但它看起來後者只適用於可調用對象。特別是,std::result_of<decltype(f)>::typeis not working。我終於想出一些代碼,工作推導獨立函數的返回類型

#include <iostream> 
#include <typeinfo> 

void f(int); // we deduce the returning type of this function 

template<typename Ret, typename... Args> 
struct Helper 
{ 
    using type = Ret; 
}; 

template<typename Ret, typename... Args> 
Helper<Ret, Args...> invoke(Ret(*fp)(Args...)) 
{ 
    return {}; 
} 

template<typename Ret, typename... Args> 
using Return_Type = typename Helper<Ret, Args...>::type; 

int main() 
{ 
    std::cout << typeid(decltype(invoke(f))::type).name() << std::endl; // fine 
} 

我在這裏使用一個附加功能,模板invoke,這需要一個指針,我想推斷返回類型的函數,並返回一個「幫手」結構,我從中讀取實際的返回類型。

該代碼似乎有點複雜,因爲它涉及調用函數(雖然沒有執行實際評估)。有沒有其他的選擇更簡單,更清楚/更短的方式來做到這一點?

+0

我猜你不要婉使用' decltype(F(0))'。 –

+0

不,因爲'f'可以有可變/未知數量的參數,並且希望某些功能適用於任何功能。 – vsoftco

+0

'result_of'可以和函數指針一起工作。 'result_of :: type'是'void'。你只是錯誤地使用它,併爲了不同的目的。 – Yakk

回答

6

諮詢我自己old blog posting關於這個,我發現:

template< class Func > 
struct ResultOf 
{ 
    typedef typename std::function< 
     typename std::remove_pointer<Func>::type 
     >::result_type T; 
}; 
+0

Upvoted。好多了。 – Nawaz

+0

太棒了!我完全錯過了可以將它包裝到'std :: function'並使用後者來處理類型的事實。 – vsoftco

+0

對於'std :: function',沒有SFINAE保證,這使得上面的短預製攻擊成爲可能。當然,大多數代碼都是從函數中提取返回值而不關心它們的調用方式。 ;) – Yakk

3
template<typename> 
struct return_t_impl; 

template<typename Ret, typename... Args> 
struct return_t_impl <Ret(Args...)> 
{ 
    using type = Ret; 
}; 

template<typename Ret, typename... Args> 
struct return_t_impl<Ret(*)(Args...)> : return_t_impl<Ret(Args...)> {}; 

template<typename T> 
using return_t = typename return_t_impl<T>::type; 

而且它的使用:

using type = return_t<decltype(f)>; //type is void 
+0

謝謝,我錯過了我可以定義部分專業化的事實。 – vsoftco

+0

第二個專業看起來很傻嗎?只要做':return_t_impl {}'? – Yakk

+0

第二個專門用於諸如'auto fptr = f;使用type = return_t ;'。在這種情況下,'fptr'被推斷爲指針函數類型,而不僅僅是函數類型。 – Nawaz

2
template<class F> 
using return_t = typename std::function<std::remove_pointer_t<std::decay_t<F>>>::result_type;