#include <iostream>
#include <iomanip>
#include <memory>
using namespace std;
template<typename FROM, typename TO>
class Adapter
{
public:
/**
* Adapts something from one type to a type.
* @param f
* @return
*/
virtual TO adapt(FROM f) = 0;
/**
* Chains adapters.
*
* @param <NEXT>
* @param next
* @return a new adapter that takes the output of this adapter and
* adapts to something of type NEXT.
*/
template<typename NEXT>
auto chain(Adapter<TO, NEXT> *next)
{
class ChainedAdapter : public Adapter<FROM, NEXT>
{
private:
Adapter<FROM, TO> *x;
Adapter<TO, NEXT> *next;
public:
ChainedAdapter(Adapter<FROM, TO> *x, Adapter<TO, NEXT> *next)
: x(x), next(next) {}
NEXT adapt(FROM f) override {
return next->adapt(x->adapt(f));
}
};
return ChainedAdapter(this, next);
}
};
class CharIntAdapter : public Adapter<char, int>
{
public:
int adapt(char f) override {
int ret = static_cast<int>(f);
cout << "char('" << f << "') -> int(" << ret << ")" << endl;
return ret;
}
};
class IntBoolAdapter : public Adapter<int, bool>
{
public:
bool adapt(int f) override {
bool ret = f != 0;
cout << "int(" << f << ") -> bool(" << boolalpha << ret << ")" << endl;
return ret;
}
};
int main() {
CharIntAdapter cia;
cout << cia.adapt('a') << endl;
cout << endl;
IntBoolAdapter iba;
cout << boolalpha << cia.chain(&iba).adapt('a') << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aW9tYW5pcD4KI2luY2x1ZGUgPG1lbW9yeT4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlPHR5cGVuYW1lIEZST00sIHR5cGVuYW1lIFRPPgpjbGFzcyBBZGFwdGVyCnsKcHVibGljOgogICAgLyoqCiAgICAgKiBBZGFwdHMgc29tZXRoaW5nIGZyb20gb25lIHR5cGUgdG8gYSB0eXBlLiAKICAgICAqIEBwYXJhbSBmCiAgICAgKiBAcmV0dXJuCiAgICAgKi8KICAgIHZpcnR1YWwgVE8gYWRhcHQoRlJPTSBmKSA9IDA7CiAgICAKICAgIC8qKgogICAgICogQ2hhaW5zIGFkYXB0ZXJzLiAKICAgICAqIAogICAgICogQHBhcmFtIDxORVhUPgogICAgICogQHBhcmFtIG5leHQgCiAgICAgKiBAcmV0dXJuIGEgbmV3IGFkYXB0ZXIgdGhhdCB0YWtlcyB0aGUgb3V0cHV0IG9mIHRoaXMgYWRhcHRlciBhbmQgCiAgICAgKiBhZGFwdHMgdG8gc29tZXRoaW5nIG9mIHR5cGUgTkVYVC4KICAgICAqLwogICAgdGVtcGxhdGU8dHlwZW5hbWUgTkVYVD4KICAgIGF1dG8gY2hhaW4oQWRhcHRlcjxUTywgTkVYVD4gKm5leHQpCiAgICB7CiAgICAJY2xhc3MgQ2hhaW5lZEFkYXB0ZXIgOiBwdWJsaWMgQWRhcHRlcjxGUk9NLCBORVhUPgogICAgCXsKICAgIAlwcml2YXRlOgoJICAgICAgICBBZGFwdGVyPEZST00sIFRPPiAqeDsgCiAgICAJICAgIEFkYXB0ZXI8VE8sIE5FWFQ+ICpuZXh0OwogICAgCXB1YmxpYzoKICAgICAgICAJQ2hhaW5lZEFkYXB0ZXIoQWRhcHRlcjxGUk9NLCBUTz4gKngsIEFkYXB0ZXI8VE8sIE5FWFQ+ICpuZXh0KQogICAgICAgICAgICAJOiB4KHgpLCBuZXh0KG5leHQpIHt9CgoJICAgICAgICBORVhUIGFkYXB0KEZST00gZikgb3ZlcnJpZGUgewogICAgCSAgICAgICAgcmV0dXJuIG5leHQtPmFkYXB0KHgtPmFkYXB0KGYpKTsKICAgICAgICAJfQoJICAgIH07CgoJCXJldHVybiBDaGFpbmVkQWRhcHRlcih0aGlzLCBuZXh0KTsKICAgIH0KfTsKCmNsYXNzIENoYXJJbnRBZGFwdGVyIDogcHVibGljIEFkYXB0ZXI8Y2hhciwgaW50Pgp7CnB1YmxpYzoKCWludCBhZGFwdChjaGFyIGYpIG92ZXJyaWRlIHsKCQlpbnQgcmV0ID0gc3RhdGljX2Nhc3Q8aW50PihmKTsKCQljb3V0IDw8ICJjaGFyKCciIDw8IGYgPDwgIicpIC0+IGludCgiIDw8IHJldCA8PCAiKSIgPDwgZW5kbDsKCQlyZXR1cm4gcmV0OwoJfQp9OwoKY2xhc3MgSW50Qm9vbEFkYXB0ZXIgOiBwdWJsaWMgQWRhcHRlcjxpbnQsIGJvb2w+CnsKcHVibGljOgoJYm9vbCBhZGFwdChpbnQgZikgb3ZlcnJpZGUgewoJCWJvb2wgcmV0ID0gZiAhPSAwOwoJCWNvdXQgPDwgImludCgiIDw8IGYgPDwgIikgLT4gYm9vbCgiIDw8IGJvb2xhbHBoYSA8PCByZXQgPDwgIikiIDw8IGVuZGw7CgkJcmV0dXJuIHJldDsKCX0KfTsKCmludCBtYWluKCkgewoJQ2hhckludEFkYXB0ZXIgY2lhOwoJY291dCA8PCBjaWEuYWRhcHQoJ2EnKSA8PCBlbmRsOwoJCgljb3V0IDw8IGVuZGw7CgkKICAgIEludEJvb2xBZGFwdGVyIGliYTsKCWNvdXQgPDwgYm9vbGFscGhhIDw8IGNpYS5jaGFpbigmaWJhKS5hZGFwdCgnYScpIDw8IGVuZGw7CgoJcmV0dXJuIDA7Cn0=