Today I learned: You can construct Boobytrapped class hierarchies in C++.
Here's an example (Godbolt link)
#include <iostream>
struct Exploder {
// Causes explosions!
};
struct Unexploder {
void roulette() {}
};
template<class T>
struct BoobyTrap : public T {
/* May or may not explode.
*/
void unsafe_call () { exploder(); }
void safe_call() {}
private:
void exploder() { T::roulette(); }
};
int main(int argc, char** argv) {
BoobyTrap<Unexploder> s;
s.safe_call();
s.unsafe_call(); // Click! We survived!
BoobyTrap<Exploder> unsafe;
unsafe.safe_call();
// Uncomment to have an explosion occur.
// Imagine this with conditional compilation?
// unsafe.unsafe_call();
return 0;
}
The wacky thing here is that you can totally use the safe_call
member function of the BoobyTrapped class independent of parent class -- because unsafe_call
is only expanded and substituted if you call it!
This feels awkward, because it divides the interface of BoobyTrap
into callable and uncallable pieces. I cant decide if I think this is a good idea or bad idea.
Pro:
- You can knit together classes, and so long as the interfaces match enough so that the interfaces work, you're OK.
Con:
- Feels like Fragile Base class ++
Thanks to Leonardo for pointing this out!