我正在探索friend
关键字与变量模板,完美转发和私有构造函数的使用。我觉得我错过了所有这些基本的东西,因为以下简单的例子不会编译。
我希望Test_Manager<Test_Class>::Process
是构建Test_Class
类型对象的唯一方法(Process
最终会做更多但这是一个简单的例子)。我还希望Test_Manager
能够管理&#39;这种方式的各种类,因此类类型的参数t_Symbol
和处理各种构造函数的可变参数...t_Args
。
// Test.cpp
#include <string>
template<typename t_Symbol>
struct Test_Manager
{
template<typename... t_Args>
static t_Symbol Process(const t_Args&... i_Args)
{
const t_Symbol New_Symbol(std::forward<t_Args>(i_Args)...); // error C2665
return New_Symbol;
}
};
class Test_Class
{
private:
friend Test_Manager<Test_Class>;
Test_Class() {};
Test_Class(const std::string& i_Text) : m_Text(i_Text) {};
const std::string m_Text;
};
void Test_Function()
{
std::string text = "hello_world";
Test_Class t = Test_Manager<Test_Class>::Process(text);
}
但是,在Visual Studio 2015 Update 3中,我收到以下错误(在上面标记的行):error C2665: 'std::forward': none of the 2 overloads could convert all the argument types
。我搞砸了什么?我觉得这应该有效。
答案 0 :(得分:3)
我在这里搞砸了什么?
是的,你是。在下面的代码中:
template<typename... t_Args>
static t_Symbol Process(const t_Args&... i_Args){
const t_Symbol New_Symbol(std::forward<t_Args>(i_Args)...);
...
}
上述问题是,i_Args
将获得const
资格,但您告诉std::forward
std::forward<t_Arg>
您将发送t_Arg
类型,但不会; t具有const
资格。
因此,基本上,std::forward<t_Args>(i_Arg)
的问题在于类型 t_Args
,不会带有隐式const
,但< em> Argument i_Arg
,有const
。
您应该在转发引用时使用std::forward
。当您这样做时,t_Arg
将隐式携带必要的 cv 资格,该资格将与i_Arg
您想将其更改为:
template<typename... t_Args>
static t_Symbol Process(t_Args&&... i_Args){
...
}
编辑,根据Guillaume Racicot的评论:
当您尝试将值移动到Process
时,例如:
Test_Manager<Test_Class>::Process(std::move(text));
Test_Class
的构造函数将击败std::forward
,因为它仍然会按照副本进行复制。
Test_Class(const std::string& i_Text) : m_Text(i_Text) {};
但是,当构造函数定义为:
时Test_Class(std::string i_Text) : m_Text(std::move(i_Text)) {};
不会复制,只会移动。
答案 1 :(得分:1)
std::forward
适用于转发引用(或通用引用),它是T&&
函数参数,其中T
是模板参数。完美转发看起来像:
template<typename... t_Args>
static t_Symbol Process(t_Args&&... i_Args)
{
t_Symbol New_Symbol(std::forward<t_Args>(i_Args)...);
return New_Symbol;
}
如果您希望Process
仅使用const
左值,那可以,但不要使用std::forward
:
template<typename... t_Args>
static t_Symbol Process(const t_Args&... i_Args)
{
t_Symbol New_Symbol(i_Args...);
return New_Symbol;
}