#include <iostream>
#include <cassert>
#include <string>
using namespace std;
auto identity = [ ] ( auto && a) { return std:: forward < decltype( a) > ( a) ; } ;
auto compose = [ ] ( auto && f, auto && g) {
return [ f, g] ( auto && val) { return f( g( std:: forward < decltype( val) > ( val) ) ) ; } ;
} ;
template < typename F, typename G>
auto operator* ( F&& f, G&& g) - > decltype( compose( f, g) ) {
return compose( std:: forward < F> ( f) , std:: forward < G> ( g) ) ;
}
int main( ) {
//identity
assert ( 5 == identity( 5 ) ) ;
assert ( "asdf" s == identity( "asdf" s) ) ;
std:: string aa = "adsf" ;
auto new_aa = identity( std:: move ( aa) ) ;
assert ( new_aa == "adsf" ) ;
assert ( aa ! = "adsf" ) ;
//composition
auto intTimes10f = [ ] ( int a) { return a * 10 .f ; } ;
auto floatTimes10s = [ ] ( float a) { return std:: to_string ( a * 10 ) + " string!" ; } ;
auto intToFloatToStringComposition = compose( floatTimes10s, intTimes10f) ;
auto compositionByOperator = floatTimes10s * intTimes10f;
std:: cout << intToFloatToStringComposition( 2 ) ;
std:: cout << "\n By operator: " << compositionByOperator( 2 ) ;
//composition and identity
auto idInComposition = compositionByOperator * identity;
std:: cout << "\n identity + last composition yields the same value: " << idInComposition( 2 ) ; //first id is applied, which yields 2 then previous composition works on this value
auto reverse = identity * compositionByOperator;
std:: cout << "\n now identity is applied after eval of previous composition: " << reverse( 2 ) ; //first composition is applied which yields std::string, then id which yields the same std::string
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y2Fzc2VydD4KI2luY2x1ZGUgPHN0cmluZz4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmF1dG8gaWRlbnRpdHkgPSBbXShhdXRvJiYgYSkgeyByZXR1cm4gc3RkOjpmb3J3YXJkPGRlY2x0eXBlKGEpPihhKTsgfTsKCmF1dG8gY29tcG9zZSA9IFtdKGF1dG8mJiBmLCBhdXRvJiYgZykgewoJcmV0dXJuIFtmLCBnXShhdXRvJiYgdmFsKSB7IHJldHVybiBmKGcoc3RkOjpmb3J3YXJkPGRlY2x0eXBlKHZhbCk+KHZhbCkpKTsgfTsKfTsKCQp0ZW1wbGF0ZTx0eXBlbmFtZSBGLCB0eXBlbmFtZSBHPgphdXRvIG9wZXJhdG9yKihGJiYgZiwgRyYmIGcpIC0+IGRlY2x0eXBlKGNvbXBvc2UoZiwgZykpIHsKCXJldHVybiBjb21wb3NlKHN0ZDo6Zm9yd2FyZDxGPihmKSwgc3RkOjpmb3J3YXJkPEc+KGcpKTsKfQoKaW50IG1haW4oKSB7CgkvL2lkZW50aXR5Cglhc3NlcnQoNSA9PSBpZGVudGl0eSg1KSk7Cglhc3NlcnQoImFzZGYicyA9PSBpZGVudGl0eSgiYXNkZiJzKSk7CglzdGQ6OnN0cmluZyBhYSA9ICJhZHNmIjsKCWF1dG8gbmV3X2FhID0gaWRlbnRpdHkoc3RkOjptb3ZlKGFhKSk7Cglhc3NlcnQobmV3X2FhID09ICJhZHNmIik7Cglhc3NlcnQoYWEgIT0gImFkc2YiKTsKCQoJLy9jb21wb3NpdGlvbgoJYXV0byBpbnRUaW1lczEwZiA9IFtdKGludCBhKSB7IHJldHVybiBhICogMTAuZjsgfTsKCWF1dG8gZmxvYXRUaW1lczEwcyA9IFtdKGZsb2F0IGEpIHsgcmV0dXJuIHN0ZDo6dG9fc3RyaW5nKGEgKiAxMCkgKyAiIHN0cmluZyEiOyB9OwoJYXV0byBpbnRUb0Zsb2F0VG9TdHJpbmdDb21wb3NpdGlvbiA9IGNvbXBvc2UoZmxvYXRUaW1lczEwcywgaW50VGltZXMxMGYpOwoJYXV0byBjb21wb3NpdGlvbkJ5T3BlcmF0b3IgPSBmbG9hdFRpbWVzMTBzICogaW50VGltZXMxMGY7CglzdGQ6OmNvdXQgPDwgaW50VG9GbG9hdFRvU3RyaW5nQ29tcG9zaXRpb24oMik7CglzdGQ6OmNvdXQgPDwgIlxuQnkgb3BlcmF0b3I6ICIgPDwgY29tcG9zaXRpb25CeU9wZXJhdG9yKDIpOwoJCgkKCS8vY29tcG9zaXRpb24gYW5kIGlkZW50aXR5CglhdXRvIGlkSW5Db21wb3NpdGlvbiA9IGNvbXBvc2l0aW9uQnlPcGVyYXRvciAqIGlkZW50aXR5OwoJc3RkOjpjb3V0IDw8ICJcbmlkZW50aXR5ICsgbGFzdCBjb21wb3NpdGlvbiB5aWVsZHMgdGhlIHNhbWUgdmFsdWU6ICIgPDwgaWRJbkNvbXBvc2l0aW9uKDIpOyAvL2ZpcnN0IGlkIGlzIGFwcGxpZWQsIHdoaWNoIHlpZWxkcyAyIHRoZW4gcHJldmlvdXMgY29tcG9zaXRpb24gd29ya3Mgb24gdGhpcyB2YWx1ZQoJCglhdXRvIHJldmVyc2UgPSBpZGVudGl0eSAqIGNvbXBvc2l0aW9uQnlPcGVyYXRvcjsKCXN0ZDo6Y291dCA8PCAiXG5ub3cgaWRlbnRpdHkgaXMgYXBwbGllZCBhZnRlciBldmFsIG9mIHByZXZpb3VzIGNvbXBvc2l0aW9uOiAiIDw8IHJldmVyc2UoMik7IC8vZmlyc3QgY29tcG9zaXRpb24gaXMgYXBwbGllZCB3aGljaCB5aWVsZHMgc3RkOjpzdHJpbmcsIHRoZW4gaWQgd2hpY2ggeWllbGRzIHRoZSBzYW1lIHN0ZDo6c3RyaW5nCgoJcmV0dXJuIDA7Cn0=