[英]Conflict between perfect forwarding constructor and copy constructor in class hierarchy
我最近在尝试使用完美的转发构造函数实现类层次结构时遇到了问题。 请考虑以下示例:
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错误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:C ++ 11中的复制构造函数 。 在没有类层次结构的其他实现中,我可以通过SFINAE禁用完美转发构造函数作为复制构造函数。 例如,参见Martinho Fernandes:转发构造函数的一些缺陷 。 当我尝试将上述解决方案应用于此示例时,我仍然无法使用相同的错误消息进行编译。
我认为一种可能的解决方案是避免完美转发,在构造函数中按值获取参数,然后从它们移动到类变量。
所以我的问题是,如果这个问题有其他一些解决方案,或者在这种情况下是否完全转发?
更新:原来我的问题很容易被误解。 所以我会尝试澄清我的意图和背景。
const string&
的示例,其中参数为const string&
和string&&
)。 尝试更改Test(const Test& other) : TestBase(other) {}
to Test(const Test& other) : TestBase(static_cast<TestBase const&>(other)) {}
第二个Test
构造函数调用TestBase,有两种可能性。 其中一个需要任何东西,另一个需要一个TestBase。 但是你正在通过测试 - “任何东西”都能更好地匹配。 通过显式地转换为TestBase const&,我们应该能够得到正确的匹配。
另一种可能性可能涉及如何构造Test - 也许你传递的是将模板构造函数与Test相匹配? 我们可以通过从Test中删除模板构造函数并查看错误是否消失来测试另一种可能性。
如果是这种情况,为什么你链接的技术(当推断的类型与Test匹配时禁用Test模板构造函数)不起作用?
让我们仔细看看错误消息。
std::basic_string<...>::basic_string(const std::basic_string<...> &) :
这意味着它适用于std::string
的复制构造函数
cannot convert parameter 1 from 'const Test' to 'const std::basic_string<..> &
实际上,没有办法从Test
转换为std::string
。 但是, Test
有一个字符串成员,即std::string s;
。
结论:看起来你忘了在那个地方添加.s
。 可能是s(std::forward<T>(t))
。
另一个可能的原因是构造函数的第一个重载被选中而不是第二个用于复制构造一个Test
实例。
以下应该工作,它不使用显式转换:
struct Test : public TestBase {
private:
static TestBase const& toBase(const Test& o) { return o; }
public:
template <typename T>
explicit Test(T&& t) : TestBase(std::forward<T>(t)) {}
Test(const Test& other) : TestBase(toBase(other)) {}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.