2014-10-31 31 views
3

我能做到這裏面decltype()爲什麼在未評估的操作數內部擴展包會導致最後一個元素?

auto g() -> decltype(1, "", true, new int); 

但不是這樣的:

template <class... Args> 
auto g(Args&&... args) -> decltype(args...); 

因爲一包擴展內出現decltype()但我認爲一包的擴展將導致逗號隔開它失敗參數列表。所以返回類型g(a, b, c)將是decltype(c),因爲逗號運算符的工作方式(它返回最後一個元素)。它可以在函數參數列表,模板參數列表,初始化列表等內部展開時使用。但爲什麼在這裏不是這種情況?

+4

我相當確定這不是它的工作原理。包擴展不會給你一個逗號分隔符的表達式。它根據上下文爲你提供不同的列表。「根據擴展發生的位置,結果的逗號分隔列表是一種不同類型的列表:函數參數列表,成員初始化列表,屬性列表等。但從來沒有給你一個逗號運算符的表達。這不僅僅是像宏一樣的文本替換。 – PeterT 2014-10-31 19:22:03

回答

5

參數包僅在某些情況下擴展。您可以通過搜索「包擴展」在標準中找到它們。例如,

函數參數包是包擴展(14.5.3)。

(8.3.5/14)。

除非明確指定在某個特定上下文中出現數據包擴展的地方,否則它不會發生,並且通常被語法禁止(,即,語法不正確)。例如,decltype需要表達式作爲其操作數。 1, "", true, new int確實是一個表達式(,是逗號運算符),但args...不是表達式。但是,args...表達式列表,所以可以使用它,例如,在函數調用中調用

4

逗號運算符與逗號表達式分隔符不同。

逗號運算符有兩個表達式,評估左側,放棄它,評估右側並返回結果。

表達式分隔符用在有表達式列表時,如函數調用或初始化列表。

decltype(a,b,c)decltype(表達),不decltype(表達式列表)。這意味着您的decltype中的,是運算符逗號。

一般而言,...擴展只適用於語法允許列表的表達式。 「生成」,是表達式分隔符,而不是逗號運算符。

我不知道您可以使用...來模擬,運算符的行爲,包括執行順序。如果你不關心他們正在評估以什麼順序,你可以這樣做:

template<class T, class... Ts> 
struct last_type_helper{using type=T;}; 
template<class T0, class T1, class... Ts> 
struct last_type_helper<T0, T1, Ts...>:last_type_helper<T1, Ts...>{} 
template<class... Ts> 
using last_type=typename last_type_helper<Ts...>::type; 

template<class T0> 
T0&& last_expression(T0&& t0) { return std::forward<T0>(t0); } 
template<class T0, class...Ts> 
auto last_expression(T0&& t0, Ts&&...ts)->last_type<T0, Ts...>&& { 
    return last_expression(std::forward<Ts>(ts)...); 
} 

然後

template<class...Args> 
auto g(Args&&...args) -> decltype(last_expression(args...)); 

作品一樣,

template<class...Args> 
auto g(Args&&...args) -> last_type<Args...>; 

這使本末倒置後,不是嗎?

相關問題