#include <iostream>
#include <type_traits>
template<class D>
class widget
{
public:
void foo() { self().bar(); }
private:
D const& self() const
{
static_assert(std::is_base_of<widget, D>(), "D must derive");
return (D const&)*this;
}
D& self()
{
auto const& that = *this;
return const_cast<D&>(that.self());
}
};
struct gadget : private widget<gadget>
{
using widget::foo;
void bar() { std::cout << "gadget\n"; }
};
int main()
{
gadget g;
g.foo();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiAKdGVtcGxhdGU8Y2xhc3MgRD4KY2xhc3Mgd2lkZ2V0CnsKcHVibGljOgoJdm9pZCBmb28oKSB7IHNlbGYoKS5iYXIoKTsgfQoKcHJpdmF0ZToKCUQgY29uc3QmIHNlbGYoKSBjb25zdAoJewoJCXN0YXRpY19hc3NlcnQoc3RkOjppc19iYXNlX29mPHdpZGdldCwgRD4oKSwgIkQgbXVzdCBkZXJpdmUiKTsKCQlyZXR1cm4gKEQgY29uc3QmKSp0aGlzOwoJfQoKCUQmIHNlbGYoKQoJewoJCWF1dG8gY29uc3QmIHRoYXQgPSAqdGhpczsKCQlyZXR1cm4gY29uc3RfY2FzdDxEJj4odGhhdC5zZWxmKCkpOwoJfQp9OwogCnN0cnVjdCBnYWRnZXQgOiBwcml2YXRlIHdpZGdldDxnYWRnZXQ+CnsKCXVzaW5nIHdpZGdldDo6Zm9vOwoJdm9pZCBiYXIoKSB7IHN0ZDo6Y291dCA8PCAiZ2FkZ2V0XG4iOyB9Cn07CiAKaW50IG1haW4oKQp7CglnYWRnZXQgZzsKCWcuZm9vKCk7Cn0K