2015-12-21 199 views
1

比方說,我有一個模板函數返回一個依賴類型。喜歡的東西:typedefing函數返回類型

template <class T> 
typename std::result_of<T()>::type 
foo() 
{ 
    std::result_of<T()>::type retVal; 
    // Some mind blowing code... 
    return retVal; 
} 

正如你所看到的,我聲明的返回值的局部變量時,曾在函數類型寫的返回類型兩次,一次,另一次。

有沒有一種方法我可以typedef這種類型的函數簽名,所以類型將只聲明一次(無代碼複製),並且只在函數(簽名和正文)內可見和可用? 喜歡的東西(警告僞代碼未來,請不要生氣或啓發!):

template <class T> 
typedef typename std::result_of<T()>::type FooReturnType 
FooReturnType foo() 
{ 
    FooReturnType retVal; 
    // Some mind blowing code... 
    return retVal; 
} 

編輯:我是僅限於C++編譯器11。

感謝

+0

嘗試將其作爲默認模板參數 – user3514538

+0

或者如果您的編譯器支持C++ 14,可能是自動返回類型? – oLen

+0

@ user3514538想過它......但是然後調用者將能夠覆蓋此值。我需要'static_assert',第二個參數確實是我想要的(仍然需要寫兩次返回類型...):( –

回答

3
template <class T> 
typename std::result_of<T()>::type 
foo() 
{ 
    decltype(foo()) retVal; 
    // Some mind blowing code... 
    return retVal; 
} 
+1

如問,這是一個很好的解決方案。如果foo在現實中有很多複雜的論點,它不會那麼好。但無論如何都要有一個贊成票。 –

2

正如評論說,有這種黑客:

template <class T, typename Ret = std::result_of_t<T()>> 
Ret foo() { 
    Ret retVal; 
    return retVal; 
} 

或者,你也許可以簡單地使用返回類型推演,如果你的編譯器是足夠新:

template <class T> 
auto foo() { 
    std::result_of_t<T()> retVal; 
    return retVal; 
} 
+0

Thanks。請參閱我上面的註釋。'auto'不存在問題(C++ 14功能)並且默認參數有點問題 –

+0

@user:那麼你應該將這些要求添加到你的問題 –

+0

@NicolBolas你是對的...完成.. –

1

您可以使用設置爲std::result_of<T()>::type的模板參數,如:

template <class T, class Ret = typename std::result_of<T()>::type> 
Ret foo() 
{ 
    Ret retVal = 100; 
    // Some mind blowing code... 
    return retVal; 
} 

Live Example

1

這是不是我們通過using允許模板的typedef?

template<typename T> 
using Ret = typename std::result_of<T()>::type; 

template<typename T> 
Ret<T> foo() 
{ 
    Ret<T> retVal; 
    // Some mind blowing code... 
    return retVal; 
} 

如果你不接受默認模板參數的傳統C++ 98/03的解決方案,你會不會接受添加using別名到的C++ 11解決方案範圍,並且你不能使用C++ 14解決方案的auto返回類型扣除,那麼就沒有解決方案。

+0

是的,但是包含此頭文件的每個人都可以看到類型。正如我在問題中所說的,我更願意避免這種情況... –

+0

我不喜歡這個解決方案的唯一的東西是它將'Ret'添加到全局範圍。如果你想這樣做與另一個,並希望'Ret'是不同的,你將不得不拿出另一個名字。 – NathanOliver

+2

@NathanOliver:然後將其粘貼到詳細的命名空間或其他任何內容中。 –