1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #include <utility> #include <type_traits> // SFINAE utility template<typename...> struct void_ { using type = void; }; template<typename... T> using Void = typename void_<T...>::type; /* * In an ideal world std::result_of would just work instead of all that. * Consider this as a write-once (until std::result_of is fixed), use-many * situation. */ template<typename Sig, typename Sfinae = void> struct result_of {}; template<typename F, typename... Args> struct result_of< F(Args...) , Void<decltype(std::declval<F>()(std::declval<Args>()...))> > { using type = decltype(std::declval<F>()(std::declval<Args>()...)); }; template<typename Sig> using ResultOf = typename result_of<Sig>::type; /* * Note how both template parameters have kind *, MonadicValue would be * m a, not m. We don't whether MonadicValue is a specialization of some M<T> * or not (or derived from a specialization of some M<T>). Note that it is * possible to retrieve the a in M a via typename MonadicValue::value_type * if MonadicValue is indeed a model of the proper concept. * * Defer actual implementation to the operator() of MonadicValue, * which will do the monad-specific operation */ template< typename MonadicValue , typename F /* It is possible to put a self-documenting assertion here that will *not* SFINAE out but truly result in a hard error unless some conditions are not satisfied -- I leave this out for brevity , Requires< MonadicValueConcept<MonadicValue> // The two following constraints ensure that // F has signature a -> m b , Callable<F, ValueType<MonadicValue>> , MonadicValueConcept<ResultOf<F(ValueType<MonadicValue>)>> >... */ > ResultOf<MonadicValue(F)> bind(MonadicValue&& value, F&& f) { return std::forward<MonadicValue>(value)(std::forward<F>(f)); } // Picking Maybe as an example monad because it's easy template<typename T> struct just_type { using value_type = T; // Encapsulation omitted for brevity value_type value; template<typename F> // The use of ResultOf means that we have a soft contraint // here, but the commented Requires clause in bind happens // before we would end up here ResultOf<F(value_type)> operator()(F&& f) { return std::forward<F>(f)(value); } }; template<typename T> just_type<T> just(T&& t) { return { std::forward<T>(t) }; } template<typename T> just_type<typename std::decay<T>::type> make_just(T&& t) { return { std::forward<T>(t) }; } struct nothing_type { // Note that because nothing_type and just_type<T> // are part of the same concept we *must* put in // a value_type member type -- whether you need // a value member or not however is a design // consideration with trade-offs struct universal { template<typename T> operator T(); }; using value_type = universal; template<typename F> nothing_type operator()(F const&) const { return {}; } }; constexpr nothing_type nothing; #include <cassert> int main() { auto maybe = make_just(4); auto f = [](int i) { return just("Hello, World!"[i]); }; auto&& r0 = bind(maybe, f); auto&& r1 = bind(bind(make_just(6), [](int i) { return just(i - 2); }), f); assert( &r0.value == &r1.value ); auto r2 = bind(nothing, f); auto r3 = bind(maybe, [](int) { return nothing; }); static_assert( std::is_same<decltype(r2), nothing_type>::value, "" ); static_assert( std::is_same<decltype(r3), nothing_type>::value, "" ); } |
I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KCi8vIFNGSU5BRSB1dGlsaXR5CnRlbXBsYXRlPHR5cGVuYW1lLi4uPiBzdHJ1Y3Qgdm9pZF8geyB1c2luZyB0eXBlID0gdm9pZDsgfTsKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVD4gdXNpbmcgVm9pZCA9IHR5cGVuYW1lIHZvaWRfPFQuLi4+Ojp0eXBlOwoKLyoKICogSW4gYW4gaWRlYWwgd29ybGQgc3RkOjpyZXN1bHRfb2Ygd291bGQganVzdCB3b3JrIGluc3RlYWQgb2YgYWxsIHRoYXQuCiAqIENvbnNpZGVyIHRoaXMgYXMgYSB3cml0ZS1vbmNlICh1bnRpbCBzdGQ6OnJlc3VsdF9vZiBpcyBmaXhlZCksIHVzZS1tYW55CiAqIHNpdHVhdGlvbi4KICovICAgIAp0ZW1wbGF0ZTx0eXBlbmFtZSBTaWcsIHR5cGVuYW1lIFNmaW5hZSA9IHZvaWQ+IHN0cnVjdCByZXN1bHRfb2Yge307CnRlbXBsYXRlPHR5cGVuYW1lIEYsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCByZXN1bHRfb2Y8CiAgICBGKEFyZ3MuLi4pCiAgICAsIFZvaWQ8ZGVjbHR5cGUoc3RkOjpkZWNsdmFsPEY+KCkoc3RkOjpkZWNsdmFsPEFyZ3M+KCkuLi4pKT4KPiB7CiAgICB1c2luZyB0eXBlID0gZGVjbHR5cGUoc3RkOjpkZWNsdmFsPEY+KCkoc3RkOjpkZWNsdmFsPEFyZ3M+KCkuLi4pKTsKfTsKdGVtcGxhdGU8dHlwZW5hbWUgU2lnPiB1c2luZyBSZXN1bHRPZiA9IHR5cGVuYW1lIHJlc3VsdF9vZjxTaWc+Ojp0eXBlOwoKLyoKICogTm90ZSBob3cgYm90aCB0ZW1wbGF0ZSBwYXJhbWV0ZXJzIGhhdmUga2luZCAqLCBNb25hZGljVmFsdWUgd291bGQgYmUKICogbSBhLCBub3QgbS4gV2UgZG9uJ3Qgd2hldGhlciBNb25hZGljVmFsdWUgaXMgYSBzcGVjaWFsaXphdGlvbiBvZiBzb21lIE08VD4KICogb3Igbm90IChvciBkZXJpdmVkIGZyb20gYSBzcGVjaWFsaXphdGlvbiBvZiBzb21lIE08VD4pLiBOb3RlIHRoYXQgaXQgaXMKICogcG9zc2libGUgdG8gcmV0cmlldmUgdGhlIGEgaW4gTSBhIHZpYSB0eXBlbmFtZSBNb25hZGljVmFsdWU6OnZhbHVlX3R5cGUKICogaWYgTW9uYWRpY1ZhbHVlIGlzIGluZGVlZCBhIG1vZGVsIG9mIHRoZSBwcm9wZXIgY29uY2VwdC4KICoKICogRGVmZXIgYWN0dWFsIGltcGxlbWVudGF0aW9uIHRvIHRoZSBvcGVyYXRvcigpIG9mIE1vbmFkaWNWYWx1ZSwKICogd2hpY2ggd2lsbCBkbyB0aGUgbW9uYWQtc3BlY2lmaWMgb3BlcmF0aW9uCiAqLwp0ZW1wbGF0ZTwKICAgIHR5cGVuYW1lIE1vbmFkaWNWYWx1ZQogICAgLCB0eXBlbmFtZSBGCiAgICAvKiBJdCBpcyBwb3NzaWJsZSB0byBwdXQgYSBzZWxmLWRvY3VtZW50aW5nIGFzc2VydGlvbiBoZXJlCiAgICAgICB0aGF0IHdpbGwgKm5vdCogU0ZJTkFFIG91dCBidXQgdHJ1bHkgcmVzdWx0IGluIGEgaGFyZCBlcnJvcgogICAgICAgdW5sZXNzIHNvbWUgY29uZGl0aW9ucyBhcmUgbm90IHNhdGlzZmllZCAtLSBJIGxlYXZlIHRoaXMgb3V0CiAgICAgICBmb3IgYnJldml0eQogICAgLCBSZXF1aXJlczwKICAgICAgICBNb25hZGljVmFsdWVDb25jZXB0PE1vbmFkaWNWYWx1ZT4KICAgICAgICAvLyBUaGUgdHdvIGZvbGxvd2luZyBjb25zdHJhaW50cyBlbnN1cmUgdGhhdAogICAgICAgIC8vIEYgaGFzIHNpZ25hdHVyZSBhIC0+IG0gYgogICAgICAgICwgQ2FsbGFibGU8RiwgVmFsdWVUeXBlPE1vbmFkaWNWYWx1ZT4+CiAgICAgICAgLCBNb25hZGljVmFsdWVDb25jZXB0PFJlc3VsdE9mPEYoVmFsdWVUeXBlPE1vbmFkaWNWYWx1ZT4pPj4KICAgID4uLi4KICAgICovCj4KUmVzdWx0T2Y8TW9uYWRpY1ZhbHVlKEYpPgpiaW5kKE1vbmFkaWNWYWx1ZSYmIHZhbHVlLCBGJiYgZikKeyByZXR1cm4gc3RkOjpmb3J3YXJkPE1vbmFkaWNWYWx1ZT4odmFsdWUpKHN0ZDo6Zm9yd2FyZDxGPihmKSk7IH0KCi8vIFBpY2tpbmcgTWF5YmUgYXMgYW4gZXhhbXBsZSBtb25hZCBiZWNhdXNlIGl0J3MgZWFzeQp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QganVzdF90eXBlIHsKICAgIHVzaW5nIHZhbHVlX3R5cGUgPSBUOwoKICAgIC8vIEVuY2Fwc3VsYXRpb24gb21pdHRlZCBmb3IgYnJldml0eQogICAgdmFsdWVfdHlwZSB2YWx1ZTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBGPgogICAgLy8gVGhlIHVzZSBvZiBSZXN1bHRPZiBtZWFucyB0aGF0IHdlIGhhdmUgYSBzb2Z0IGNvbnRyYWludAogICAgLy8gaGVyZSwgYnV0IHRoZSBjb21tZW50ZWQgUmVxdWlyZXMgY2xhdXNlIGluIGJpbmQgaGFwcGVucwogICAgLy8gYmVmb3JlIHdlIHdvdWxkIGVuZCB1cCBoZXJlCiAgICBSZXN1bHRPZjxGKHZhbHVlX3R5cGUpPgogICAgb3BlcmF0b3IoKShGJiYgZikKICAgIHsgcmV0dXJuIHN0ZDo6Zm9yd2FyZDxGPihmKSh2YWx1ZSk7IH0KfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+Cmp1c3RfdHlwZTxUPiBqdXN0KFQmJiB0KQp7IHJldHVybiB7IHN0ZDo6Zm9yd2FyZDxUPih0KSB9OyB9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpqdXN0X3R5cGU8dHlwZW5hbWUgc3RkOjpkZWNheTxUPjo6dHlwZT4gbWFrZV9qdXN0KFQmJiB0KQp7IHJldHVybiB7IHN0ZDo6Zm9yd2FyZDxUPih0KSB9OyB9CgpzdHJ1Y3Qgbm90aGluZ190eXBlIHsKICAgIC8vIE5vdGUgdGhhdCBiZWNhdXNlIG5vdGhpbmdfdHlwZSBhbmQganVzdF90eXBlPFQ+CiAgICAvLyBhcmUgcGFydCBvZiB0aGUgc2FtZSBjb25jZXB0IHdlICptdXN0KiBwdXQgaW4KICAgIC8vIGEgdmFsdWVfdHlwZSBtZW1iZXIgdHlwZSAtLSB3aGV0aGVyIHlvdSBuZWVkCiAgICAvLyBhIHZhbHVlIG1lbWJlciBvciBub3QgaG93ZXZlciBpcyBhIGRlc2lnbgogICAgLy8gY29uc2lkZXJhdGlvbiB3aXRoIHRyYWRlLW9mZnMKICAgIHN0cnVjdCB1bml2ZXJzYWwgeyB0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBvcGVyYXRvciBUKCk7IH07CiAgICB1c2luZyB2YWx1ZV90eXBlID0gdW5pdmVyc2FsOwoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIEY+CiAgICBub3RoaW5nX3R5cGUgb3BlcmF0b3IoKShGIGNvbnN0JikgY29uc3QKICAgIHsgcmV0dXJuIHt9OyB9Cn07CmNvbnN0ZXhwciBub3RoaW5nX3R5cGUgbm90aGluZzsKICAgIAojaW5jbHVkZSA8Y2Fzc2VydD4KICAgIAppbnQgbWFpbigpCnsKICAgIGF1dG8gbWF5YmUgPSBtYWtlX2p1c3QoNCk7CiAgICBhdXRvIGYgPSBbXShpbnQgaSkgeyByZXR1cm4ganVzdCgiSGVsbG8sIFdvcmxkISJbaV0pOyB9OwogICAgYXV0byYmIHIwID0gYmluZChtYXliZSwgZik7CiAgICBhdXRvJiYgcjEgPSBiaW5kKGJpbmQobWFrZV9qdXN0KDYpLCBbXShpbnQgaSkgeyByZXR1cm4ganVzdChpIC0gMik7IH0pLCBmKTsKICAgIGFzc2VydCggJnIwLnZhbHVlID09ICZyMS52YWx1ZSApOwogICAgYXV0byByMiA9IGJpbmQobm90aGluZywgZik7CiAgICBhdXRvIHIzID0gYmluZChtYXliZSwgW10oaW50KSB7IHJldHVybiBub3RoaW5nOyB9KTsKICAgIHN0YXRpY19hc3NlcnQoIHN0ZDo6aXNfc2FtZTxkZWNsdHlwZShyMiksIG5vdGhpbmdfdHlwZT46OnZhbHVlLCAiIiApOwogICAgc3RhdGljX2Fzc2VydCggc3RkOjppc19zYW1lPGRlY2x0eXBlKHIzKSwgbm90aGluZ190eXBlPjo6dmFsdWUsICIiICk7Cn0=
prog.cpp:5:44: error: expected nested-name-specifier before 'type' prog.cpp:5:44: error: using-declaration for non-member at class scope prog.cpp:5:49: error: expected ';' before '=' token prog.cpp:5:49: error: expected unqualified-id before '=' token prog.cpp:6:25: error: expected unqualified-id before 'using' prog.cpp:17:7: error: 'Void' was not declared in this scope prog.cpp:17:64: error: template argument 2 is invalid prog.cpp:18:1: error: expected unqualified-id before '>' token prog.cpp:21:24: error: expected unqualified-id before 'using' prog.cpp:49:1: error: 'ResultOf' does not name a type prog.cpp:54:1: error: expected unqualified-id before 'template' prog.cpp:71:1: error: 'just_type' does not name a type prog.cpp:74:1: error: expected unqualified-id before 'template' prog.cpp:85:11: error: expected nested-name-specifier before 'value_type' prog.cpp:85:11: error: using-declaration for non-member at class scope prog.cpp:85:22: error: expected ';' before '=' token prog.cpp:85:22: error: expected unqualified-id before '=' token prog.cpp:91:24: error: missing initializer for constexpr 'nothing' prog.cpp: In function 'int main()': prog.cpp:97:29: error: 'make_just' was not declared in this scope prog.cpp:97:29: error: unable to deduce 'auto' from '<expression error>' prog.cpp: In lambda function: prog.cpp:98:56: error: 'just' was not declared in this scope prog.cpp:98:59: error: return-statement with a value, in function returning 'void' prog.cpp: In function 'int main()': prog.cpp:99:30: error: 'bind' was not declared in this scope prog.cpp:99:30: error: unable to deduce 'auto&&' from '<expression error>' prog.cpp: In lambda function: prog.cpp:100:70: error: 'just' was not declared in this scope prog.cpp:100:73: error: return-statement with a value, in function returning 'void' prog.cpp: In function 'int main()': prog.cpp:100:78: error: unable to deduce 'auto&&' from '<expression error>' prog.cpp:102:30: error: unable to deduce 'auto' from '<expression error>' prog.cpp:103:54: error: unable to deduce 'auto' from '<expression error>' prog.cpp:104:59: error: template argument 1 is invalid prog.cpp:105:59: error: template argument 1 is invalid
-
result: Compilation error (maybe you wish to see an example for C++11)


