禁用 CRTP 模板中的复制分配
Posted
技术标签:
【中文标题】禁用 CRTP 模板中的复制分配【英文标题】:Disable copy assigment in CRTP-template 【发布时间】:2021-10-22 19:01:42 【问题描述】:我有一个CRTP 模板,我在其中使用了一个对象池。使用 generate() 静态方法分配对象。
template <class tDerivedSignal, class tBridgeType, class tPayLoadType = void>
class SignalT : public SignalSignatureT<tBridgeType>
...
static tDerivedSignal &generate(tPayLoadType &fPayLoad)
tDerivedSignal &rtnVal = Pool::reserve();
// Copy pay load to signal instance
rtnVal.mPayLoad = fPayLoad;
// Return generated signal
return(rtnVal);
...
现在,问题是我不想阻止像这样的复制分配
DerivedSignal sig = DerivedSignal::generate()
原因是副本 sig 可能具有本地范围并变得无效/被破坏,这将在以后用户尝试使用它时产生段错误.此外,分配的池对象将丢失并泄漏内存。我希望上面的复制分配生成编译时错误,但引用分配例如
DerivedSignal &sig = DerivedSignal::generate()
应该没问题。我试图删除 CRTP 模板中的赋值运算符,但没有成功:
template <class tDerivedSignal, class tBridgeType, class tPayLoadType = void>
class SignalT : public SignalSignatureT<tBridgeType>
...
// Disable copy assignment operator to prevent a generated signal from being copied into
// a new instance that is not under pool management
tDerivedSignal operator=(const tDerivedSignal &) = delete;
tDerivedSignal operator=(const tDerivedSignal) = delete;
...
有人知道吗?
【问题讨论】:
不是赋值,是复制构造。你想要tDerivedSignal(const tDerivedSignal&) = delete;
我最初的想法相同,但在 GCC 4.7 上无法编译。我在“const”之前得到“预期的不合格 ID”
哦,抱歉,被代码中的某些东西弄糊涂了,复制构造(以及通常的复制赋值)是在当前类型上完成的,所以你只需要SignalT(cont SignalT) = delete
您不应该忽略您使用 GCC 4.7。它对 C++11 的支持仍处于试验阶段。我们提供的有效 C++11 建议可能不起作用。
这也是不行的,因为(我相信)复制构造删除仅适用于 SignatT 类型而不适用于派生类型。如果我这样做 DerivedSignal(const DerivedSignal&) = delete;它可以工作,但这样会使模板的目的无效。
【参考方案1】:
您想要删除 SignalT 复制分配(并且很可能是复制构造)。默认情况下,任何继承自此的类(如在您的 CRTP 模式中)都将删除其默认的复制构造函数/复制赋值运算符,这也将禁止默认的移动构造/移动赋值运算符。
template <class tDerivedSignal, class tBridgeType, class tPayLoadType = void>
class SignalT : public SignalSignatureT<tBridgeType>
...
// Disable copy assignment operator to prevent a generated signal from being copied into
// a new instance that is not under pool management
void SignalT operator=(const SignalT&) = delete;
// You probably also want to delete copy construction
SignalT(SignalT const&) =delete;
...
【讨论】:
在我的一个小问题之后,以下工作:SignalT(SignalT const&) = delete;
SignalT() = default;
SignalT operator=(const SignalT&) = delete
在我的一个模板特化中给出了错误(无效的抽象返回类型)。
你想要返回 SignalT&,以避免这种情况,但老实说,当我删除赋值运算符时,我倾向于返回 void(从 C++03 天开始的习惯,当我会声明函数,但不定义它,并将其设为私有。以上是关于禁用 CRTP 模板中的复制分配的主要内容,如果未能解决你的问题,请参考以下文章
如何快速禁用 SkyFloatingLabelTextField 中的复制粘贴功能?
AWS API Gateway REST API 是不是没有设置来禁用 CloudFormation 模板中的 execute-api 端点?