微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 类层次结构中完美转发构造函数和复制构造函数之间的冲突

我最近在尝试使用完美的转发构造函数实现类层次结构时遇到了问题.
请考虑以下示例:
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,_Alloc> &)’ : cannot convert parameter 1 from ‘const Test’ to ‘const std::basic_string<_Elem,_Alloc> &’

我的理解是编译器将完美的转发构造函数视为比复制构造函数更好的数学运算.例如,参见Scott Meyers: Copying Constructors in C++11 .在没有类层次结构的其他实现中,我可以通过SFINAE禁用完美转发构造函数作为复制构造函数.请参阅例如Martinho Fernandes: Some pitfalls with forwarding constructors.当我尝试将上述解决方案应用于此示例时,我仍然无法使用相同的错误消息进行编译.

我认为一种可能的解决方案是避免完美转发,在构造函数中按值获取参数,然后从它们移动到类变量.

所以我的问题是,如果这个问题有其他一些解决方案,或者在这种情况下不可能完美转发?

更新:
事实证明,我的问题很容易被误解.所以我会尝试澄清我的意图和背景.

>代码完整,就像发布在问题中一样.没有创建其他对象或调用函数.尝试编译发布的示例时出现错误.
>拥有完美的转发构造函数的目的是成员初始化,而不是拥有某种额外的复制构造函数.这里的原因是在使用临时对象初始化成员时保存一些对象副本(正如Scott Meyers在会谈中提出的那样)
>不幸的是,事实证明,完美的转发构造函数可能会与其他重载的构造函数冲突(在此示例中使用复制构造函数).
>类似于对这个问题的答案和评论建议:这里可能的解决方案是引入显式强制转换或具有单独的非模板化构造函数(即,关于具有两个构造函数的示例,其中参数为const 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模板构造函数)不起作用?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐