[英]Perfect Forwarding to a Private Class Constructor Through a Templated Friend Class
我正在探索可變參數模板,完美轉發和私有構造函數中對friend
關鍵字的使用。 我覺得我缺少所有這些基本知識,因為下面的簡單示例無法編譯。
我希望Test_Manager<Test_Class>::Process
是構造類型為Test_Class
的對象的唯一方法( Process
最終會做更多的事情,但這是一個簡單的示例)。 我還希望Test_Manager
能夠以這種方式“管理”各種類,因此類類型的參數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
。 我在這里搞砸了嗎? 我覺得這應該工作。
我在這里搞砸了嗎?
是的,你是。 在下面的代碼中:
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>
您將發送一個不包含const
限定符的t_Arg
類型。
因此,從本質std::forward<t_Args>(i_Arg)
,您的std::forward<t_Args>(i_Arg)
的問題在於類型 t_Args
不帶有隱式const
,但是參數 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
的構造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)) {};
不會復制,只能移動。
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.