I've written a class to facilitate type erasure that has the following constructors:
class Envelope {
public:
Envelope() {}
template<typename Runnable>
Envelope(Runnable runnable)
: m_runFunc(&Envelope::RunAndDeleteRunnable<Runnable>), m_runnable(new Runnable(runnable)) {
}
template<typename Runnable>
Envelope(Runnable * runnable)
: m_runFunc(&Envelope::RunRunnable<Runnable>), m_runnable(runnable) {
}
};
I want to rewrite the first non-default constructor to take a reference rather than a value (Runnable & runnable rather than Runnable runnable), but if I do that then copying with a non-const Envelope like so
Envelope next(...);
Envelope otherNext(next);
invokes that constructor rather than the copy constructor, and I get a stack overflow.
I think I can prevent that constructor from being called when Runnable == Envelope with std::enable_if like so
template<typename Runnable = typename std::enable_if<std::negate<std::is_same<Runnable, Nova::Envelope>>::value, Runnable>::type>
Envelope(Runnable & runnable)
: m_runFunc(&Envelope::RunAndDeleteRunnable<Runnable>), m_runnable(new Runnable(runnable)) {
}
and it compiles fine (although it triggers some intellisense errors in Visual Studio 2015, which is mildly annoying), but it doesn't stop that constructor from being called with non-const Envelopes and triggering a stack overflow.
I'm not entirely sure what I'm doing wrong here.