我最近在尝试使用完美转发构造函数实现类层次结构时遇到了一个问题。
考虑以下示例:
当我尝试编译代码时,我得到了以下错误:
错误3 error C2664: 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string(const std::basic_string<_Elem,_Traits,_Alloc> &)' :无法将参数1从'const Test'转换为'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&&)。
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) {}
};
当我尝试编译代码时,我得到了以下错误:
错误3 error C2664: 'std::basic_string<_Elem,_Traits,_Alloc>::basic_string(const std::basic_string<_Elem,_Traits,_Alloc> &)' :无法将参数1从'const Test'转换为'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(test)
而不是std :: string(test.s)
吗?请向我们展示main.cc文件中的第130行。 - Andriys(std::forward<T>(t))
而不是s(std::forward<T>(t).s)
。 - avakarstring
创建一个单一的构造函数,并添加一个转发的make_test
函数 模板。 - Kerrek SB