2016-12-10 44 views
3

使用可變參數模板時遇到了兩種不同的編寫std::forward調用的方法,但我仍然想知道兩種語法之間的實際區別是什麼?可變參數模板參數包轉發中的語法差異

template<typename... T> 
void one(T&&... args) 
{ 
    foo(std::forward<T&&...>(args...)); 
} 
template<typename... T> 
void two(T&&... args) 
{ 
    foo(std::forward<T&&>(args)...); 
} 

根據我的編譯器,這些都是有效的語法,並且在大多數情況下編譯器不會抱怨。但是我發現了一些情況,其中一個或另一個是正確的,但編譯器沒有詳細說明爲什麼。

另一個更正確嗎?
他們是否有不同的用途?

+9

第一個錯誤,除了一個元素包之外實際上不會編譯。 –

+0

這就是所謂的包裝展開。用'one(2,2.3,2.3f);'調用第一個例子會使函數體foo(std :: forward (2,2.3,2.3f)'不能編譯。 – DeiDei

回答

6

...放置告訴編譯器在哪裏擴展包,一次爲它之前的東西的每個元素(很難輕鬆地說出,但我會在下面說明)。

讓我們考慮一個包T = {int, double, char}args = {1, 2.0, '3'}

你的第一個例子(one)將擴大T<>內,然後()args所以它成爲

foo(std::forward<T&&...>(args...)); // becomes: 
foo(std::forward<int&&, double&&, char&&>(1, 2.0, '3')); 

這不是如何std::forward因爲它只能期待一個論點。你的第二個例子(two)說,擴大到std::forward整個呼叫一次在包裝每一個項目,所以它成爲

foo(std::forward<T&&>(args)...); // becomes: 
foo(std::forward<int&&>(1), std::forward<double&&>(2.0),std::forward<char&&>('3')); 

至於爲什麼這些都編細,結果是相同的,如果你只有一個叫論據。如果你從來沒有調用它,那麼它將不會被實例化。