通过模板化朋友 Class 完美转发到私有 Class 构造函数
Perfect Forwarding to a Private Class Constructor Through a Templated Friend Class
我正在探索 friend
关键字与可变参数模板、完美转发和私有构造函数的用法。我觉得我错过了所有这一切的一些基本知识,因为以下简单示例无法编译。
我希望 Test_Manager<Test_Class>::Process
是构造类型 Test_Class
对象的唯一方法(Process
最终会做更多,但这是一个微不足道的例子)。我还希望 Test_Manager
能够以这种方式 'manage' 各种 classes,因此 class 类型的参数 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
。我在这里搞砸了什么?我觉得这应该行得通。
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;
}
What am I screwing up here?
是的,你是。在下面的代码中:
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
类型,这不会' 具有 const
资格。
所以,从本质上讲,您的 std::forward<t_Args>(i_Arg)
的问题在于 Type t_Args
没有隐含的 const
,但是 Argument i_Arg
有一个 const
.
您应该在转发引用时使用 std::forward
。当你这样做时,t_Arg
将隐式携带必要的 cv 资格,这将匹配 i_Arg
的 cv 资格
您想将其更改为:
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)) {};
不会复制,只会移动
我正在探索 friend
关键字与可变参数模板、完美转发和私有构造函数的用法。我觉得我错过了所有这一切的一些基本知识,因为以下简单示例无法编译。
我希望 Test_Manager<Test_Class>::Process
是构造类型 Test_Class
对象的唯一方法(Process
最终会做更多,但这是一个微不足道的例子)。我还希望 Test_Manager
能够以这种方式 'manage' 各种 classes,因此 class 类型的参数 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
。我在这里搞砸了什么?我觉得这应该行得通。
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;
}
What am I screwing up here?
是的,你是。在下面的代码中:
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
类型,这不会' 具有 const
资格。
所以,从本质上讲,您的 std::forward<t_Args>(i_Arg)
的问题在于 Type t_Args
没有隐含的 const
,但是 Argument i_Arg
有一个 const
.
您应该在转发引用时使用 std::forward
。当你这样做时,t_Arg
将隐式携带必要的 cv 资格,这将匹配 i_Arg
的 cv 资格
您想将其更改为:
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)) {};
不会复制,只会移动