作者:手机用户2502853355 | 来源:互联网 | 2023-02-04 10:19
我写了一个类来促进类型擦除,它有以下构造函数:
class Envelope {
public:
Envelope() {}
template
Envelope(Runnable runnable)
: m_runFunc(&Envelope::RunAndDeleteRunnable), m_runnable(new Runnable(runnable)) {
}
template
Envelope(Runnable * runnable)
: m_runFunc(&Envelope::RunRunnable), m_runnable(runnable) {
}
};
我想重写第一个非默认构造方法来参考,而不是一个值(Runnable & runnable
不是Runnable runnable
),但如果我这样做,那么用非const复制Envelope
像这样
Envelope next(...);
Envelope otherNext(next);
调用该构造函数而不是复制构造函数,我得到一个堆栈溢出.
我想我可以防止构造的时候被称为Runnable
== Envelope
有std::enable_if
像这样
template>::value, Runnable>::type>
Envelope(Runnable & runnable)
: m_runFunc(&Envelope::RunAndDeleteRunnable), m_runnable(new Runnable(runnable)) {
}
它编译得很好(尽管它在Visual Studio 2015中触发了一些智能感知错误,这有点令人讨厌),但它并没有阻止该构造函数被非const调用Envelope
并触发堆栈溢出.
我不完全确定我在这里做错了什么.
1> Nir Friedman..:
防止这种情况的最简单方法是添加"非常量"复制构造函数:
class Envelope {
public:
Envelope() {}
Envelope(const Envelope&) = default;
Envelope(Envelope& e) : Envelope(const_cast(e)) {}
...
}
};
你没有做任何特别错误的事情,只是当你编写带有一个模板化参数(或可变参数)的构造函数时,它们往往是"粘性的"并拦截用于复制构造函数的东西.在选择调用哪个函数时,复制构造函数没有得到任何特殊处理.模板化函数只是非const对象的更好匹配.通过添加与非const情况匹配的具体(非模板),现在将在该函数和模板之间存在匹配优势.在平局的情况下,函数总是击败模板.