我最近在嘗試使用完美的轉發構造函數實現類層次結構時遇到了問題。 請看下面的例子:在類層次結構中完美的轉發構造函數和複製構造函數之間的衝突
struct TestBase {
template<typename T>
explicit TestBase(T&& t) : s(std::forward<T>(t)) {} // Compiler refers to this line in the error message
TestBase(const TestBase& other) : s(other.s) {}
std::string s;
};
struct Test : public TestBase {
template<typename T>
explicit Test(T&& t) : TestBase(std::forward<T>(t)) {}
Test(const Test& other) : TestBase(other) {}
};
當我嘗試編譯代碼我收到以下錯誤:
Error 3 error C2664: 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string(const std::basic_string<_Elem,_Traits,_Alloc> &)' : cannot convert parameter 1 from 'const Test' to 'const std::basic_string<_Elem,_Traits,_Alloc> &'
我的理解是,編譯器將完美轉發構造函數比一個更好的數學複製構造函數。例如參見Scott Meyers: Copying Constructors in C++11。在沒有類層次結構的其他實現中,我可以通過SFINAE禁用完美的轉發構造函數作爲複製構造函數。例如參見Martinho Fernandes: Some pitfalls with forwarding constructors。當我嘗試將上述解決方案應用於此示例時,我仍然無法使用相同的錯誤消息進行編譯。
我認爲一個可能的解決方案是避免完美的轉發,按構造函數中的值取參數,並從它們移動到類變量。
所以我的問題是,如果有這個問題的其他解決方案,或者如果在這種情況下不可能完美轉發?
更新: 原來,我的問題是容易產生誤解。所以我會試着澄清我的意圖和背景。
- 該代碼是完全像發佈在問題中。沒有創建其他對象或調用函數。嘗試編譯發佈的示例時出現錯誤。
- 擁有完美的轉發構造函數的目的是爲了成員初始化,並且而不是有一些額外的拷貝構造函數。原因在於在初始化具有臨時對象的成員時保存一些對象副本(如Scott Meyers的談話中提出的那樣)
- 不幸的是,事實證明,完美的轉發構造函數可能與其他重載的構造函數衝突(在本例中使用複製構造函數) 。
- 一樣的答案和評論對這個問題建議:可能的解決方案在這裏將引入顯式轉換或具有獨立的非模板的構造函數(即關於分別具有兩個構造帶參數
const string&
和string&&
的例子)。
也許這是你寫的東西像'的std :: string(測試)',而不是'的std :: string(test.s) '?請向我們展示main.cc – Andrey
的第130行,你寫了's(std :: forward(t))'而不是s(std :: forward (t).s)''。 –
avakar
混合過載和轉發模板通常是一個糟糕的主意。我從'string'創建一個構造函數並添加一個轉發'make_test' *函數*模板。 –