2016-11-27 90 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

相关问题