#include <cassert>
#include <iostream>
template<typename T, typename R=void>
struct ExtMethod {
ExtMethod& operator - () {
return *this;
}
template<typename U>
R operator()( U& obj ) {
return static_cast<T*>(this)->operator()( obj );
}
};
template<typename Derived>
struct Extendible
{
template<typename T, typename ReturnT>
ReturnT operator < ( ExtMethod<T, ReturnT>& extMethod ) {
return extMethod( static_cast<Derived&>( *this ) );
}
};
struct Widget : Extendible<Widget> {
Widget( int size, int weight ) : size( size ), weight( weight ) {}
int size;
int weight;
};
struct print : ExtMethod<print> {
void operator()( Widget& w ) {
std::cout << "size: " << w.size << ", weight: " << w.weight << std::endl;
}
};
struct density : ExtMethod<density, float> {
float operator()( Widget& w ) {
return (float)(w.weight / w.size);
}
};
int main() {
Widget w( 4, 10 );
w<-print();
float d = w<-density();
assert( d - 10/4 < 0.01 );
}
I2luY2x1ZGUgPGNhc3NlcnQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFI9dm9pZD4Kc3RydWN0IEV4dE1ldGhvZCB7CiAgICBFeHRNZXRob2QmIG9wZXJhdG9yIC0gKCkgewogICAgICAgIHJldHVybiAqdGhpczsKICAgIH0KICAgIAogICAgdGVtcGxhdGU8dHlwZW5hbWUgVT4KICAgIFIgb3BlcmF0b3IoKSggVSYgb2JqICkgewogICAgICAgIHJldHVybiBzdGF0aWNfY2FzdDxUKj4odGhpcyktPm9wZXJhdG9yKCkoIG9iaiApOwogICAgfQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgRGVyaXZlZD4Kc3RydWN0IEV4dGVuZGlibGUKewogICAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgUmV0dXJuVD4KICAgIFJldHVyblQgb3BlcmF0b3IgPCAoIEV4dE1ldGhvZDxULCBSZXR1cm5UPiYgZXh0TWV0aG9kICkgewogICAgICAgIHJldHVybiBleHRNZXRob2QoIHN0YXRpY19jYXN0PERlcml2ZWQmPiggKnRoaXMgKSApOwogICAgfQp9OwoKc3RydWN0IFdpZGdldCA6IEV4dGVuZGlibGU8V2lkZ2V0PiB7CiAgICBXaWRnZXQoIGludCBzaXplLCBpbnQgd2VpZ2h0ICkgOiBzaXplKCBzaXplICksIHdlaWdodCggd2VpZ2h0ICkge30KICAgIAogICAgaW50IHNpemU7CiAgICBpbnQgd2VpZ2h0Owp9OwpzdHJ1Y3QgcHJpbnQgOiBFeHRNZXRob2Q8cHJpbnQ+IHsKICAgIHZvaWQgb3BlcmF0b3IoKSggV2lkZ2V0JiB3ICkgewogICAgICAgIHN0ZDo6Y291dCA8PCAic2l6ZTogIiA8PCB3LnNpemUgPDwgIiwgd2VpZ2h0OiAiIDw8IHcud2VpZ2h0IDw8IHN0ZDo6ZW5kbDsKICAgIH0KfTsKc3RydWN0IGRlbnNpdHkgOiBFeHRNZXRob2Q8ZGVuc2l0eSwgZmxvYXQ+IHsKICAgIGZsb2F0IG9wZXJhdG9yKCkoIFdpZGdldCYgdyApIHsKICAgICAgIHJldHVybiAoZmxvYXQpKHcud2VpZ2h0IC8gdy5zaXplKTsKICAgIH0KfTsKCmludCBtYWluKCkgewoKICAgIFdpZGdldCB3KCA0LCAxMCApOwogICAgdzwtcHJpbnQoKTsKCiAgICBmbG9hdCBkID0gdzwtZGVuc2l0eSgpOwogICAgYXNzZXJ0KCBkIC0gMTAvNCA8IDAuMDEgKTsKfQ==