#include <iostream>
namespace so {
template<typename _t_derived_>
class _animal_ {
private:
using _derived_ = _t_derived_;
public:
void eat() const {
static_cast<_derived_ const *>(this)->eat_impl();
}
};
class _dog_: public _animal_<_dog_> {
friend class _animal_<_dog_> ;
private:
using _base_ = _animal_<_dog_>;
protected:
void eat_impl() const {
std::cout << "dog's eating." << std::endl;
}
};
class _cat_: public _animal_<_cat_> {
friend class _animal_<_cat_> ;
private:
using _base_ = _animal_<_cat_>;
protected:
void eat_impl() const {
std::cout << "cat's eating." << std::endl;
}
};
template<typename _t_animal_>
void feed(_t_animal_ const & _animal) {
std::cout << "feeding an animal: ";
_animal.eat();
}
} // namespace so
int main() {
so::_dog_ dog_;
so::_cat_ cat_;
so::feed(dog_);
so::feed(cat_);
return (0);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKbmFtZXNwYWNlIHNvIHsKdGVtcGxhdGU8dHlwZW5hbWUgX3RfZGVyaXZlZF8+CmNsYXNzIF9hbmltYWxfIHsKcHJpdmF0ZToKCXVzaW5nIF9kZXJpdmVkXyA9IF90X2Rlcml2ZWRfOwpwdWJsaWM6Cgl2b2lkIGVhdCgpIGNvbnN0IHsKCQlzdGF0aWNfY2FzdDxfZGVyaXZlZF8gY29uc3QgKj4odGhpcyktPmVhdF9pbXBsKCk7Cgl9Cn07CgpjbGFzcyBfZG9nXzogcHVibGljIF9hbmltYWxfPF9kb2dfPiB7CglmcmllbmQgY2xhc3MgX2FuaW1hbF88X2RvZ18+IDsKcHJpdmF0ZToKCXVzaW5nIF9iYXNlXyA9IF9hbmltYWxfPF9kb2dfPjsKcHJvdGVjdGVkOgoJdm9pZCBlYXRfaW1wbCgpIGNvbnN0IHsKCQlzdGQ6OmNvdXQgPDwgImRvZydzIGVhdGluZy4iIDw8IHN0ZDo6ZW5kbDsKCX0KfTsKCmNsYXNzIF9jYXRfOiBwdWJsaWMgX2FuaW1hbF88X2NhdF8+IHsKCWZyaWVuZCBjbGFzcyBfYW5pbWFsXzxfY2F0Xz4gOwpwcml2YXRlOgoJdXNpbmcgX2Jhc2VfID0gX2FuaW1hbF88X2NhdF8+Owpwcm90ZWN0ZWQ6Cgl2b2lkIGVhdF9pbXBsKCkgY29uc3QgewoJCXN0ZDo6Y291dCA8PCAiY2F0J3MgZWF0aW5nLiIgPDwgc3RkOjplbmRsOwoJfQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgX3RfYW5pbWFsXz4Kdm9pZCBmZWVkKF90X2FuaW1hbF8gY29uc3QgJiBfYW5pbWFsKSB7CglzdGQ6OmNvdXQgPDwgImZlZWRpbmcgYW4gYW5pbWFsOiAiOwoJX2FuaW1hbC5lYXQoKTsKfQp9IC8vIG5hbWVzcGFjZSBzbwoKaW50IG1haW4oKSB7Cglzbzo6X2RvZ18gZG9nXzsKCXNvOjpfY2F0XyBjYXRfOwoKCXNvOjpmZWVkKGRvZ18pOwoJc286OmZlZWQoY2F0Xyk7CgoJcmV0dXJuICgwKTsKfQ==