2016-11-27 92 views
3

我想了解C++轉發的概念,並在代碼中寫下以瞭解variadic模板上的此功能。完美轉發不在C++中工作

#include<utility> 
#include<string> 
#include<tuple> 
#include<sstream> 

template<typename... Args> struct Helper_Class 
{ 
    std::tuple<Args...> argTuple; 
    Helper_Class(Args&&... args): 
        argTuple(std::make_tuple(std::forward<Args>(args)...)) 
    {} 
}; 

template<typename... Args> std::ostream& 
operator<< (std::ostream& os,Helper_Class<Args...> obj) 
{ 
    return os; 
} 

template<typename...Args> 
Helper_Class< Args...> 
Print(Args&&... args) 
{ 
    return Helper_Class<Args...>(std::forward<Args>(args)...); 
} 

template <typename... Ts> 
void test(Ts &&...params) { 
    std::stringstream s; 
    s <<Print(std::forward<Ts>(params)...); 
} 

int main() 
{ 
    test(1,2,"foo", 'x'); 
} 

然而,在執行我收到以下錯誤代碼:

error: no matching function for call to ‘std::tuple<int, int, const char (&)[4], char>::tuple(std::tuple<int, int, const char*, char>)’ 
     argTuple(std::make_tuple(std::forward<Args>(args)...)) 

什麼我不理解是,如果我試圖做完美轉發(指類型不應該函數調用之間變化)爲什麼它試圖改變類型?

請原諒這是非常基本的,因爲我第一次學習這個概念。

更新1: 延續的問題張貼在:Question

回答

5
template <typename... Ts> 
void test(Ts &&...params) { 
    std::stringstream s; 
    s <<Print(std::forward<Ts>(params)...); 
} 

你會從這裏開始。 Print的模板參數將出自std::forward。因此,它們已經被轉發左值/右值引用等。這就是你要在這裏推出的,作爲Print模板的參數。

然後:

template<typename...Args> 
Helper_Class< Args...> 
Print(Args&&... args) 

這是現在要轉發Args...Helper_Class,這將使用這些類型嘗試聲明包含左值引用,右值引用,等人的元組。這不會奏效。

need to decay這些吸盤:

template<typename...Args> 
Helper_Class< typename std::decay<Args>::type...> 
Print(Args&&... args) 
{ 
    return Helper_Class<typename std::decay<Args>::type...>(std::forward<Args>(args)...); 
} 

或者,讓我們使用C++ 14來清理一些視覺上的混亂......

template<typename...Args> 
auto Print(Args&&... args) 
{ 
    return Helper_Class<typename std::decay<Args>::type...>(std::forward<Args>(args)...); 
} 

現在這編譯對我來說,用gcc 6.2。 1。

P.S.這並不完全是「基本的」...

+0

你也可以使用'decay_t',所以你不需要'typename'或':: type' – 0x499602D2

+0

現在只能接受rvalues而不是lvalues。 – 0x499602D2

相關問題