{"id":18714156,"url":"https://github.com/pfultz2/pythy","last_synced_at":"2025-04-12T12:31:46.294Z","repository":{"id":4453481,"uuid":"5592055","full_name":"pfultz2/Pythy","owner":"pfultz2","description":"Having it all now: Pythy syntax for C++11","archived":false,"fork":false,"pushed_at":"2012-10-23T23:10:22.000Z","size":1301,"stargazers_count":23,"open_issues_count":3,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-26T07:11:20.030Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pfultz2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-08-28T21:02:07.000Z","updated_at":"2019-07-14T16:32:17.000Z","dependencies_parsed_at":"2022-09-20T23:22:04.012Z","dependency_job_id":null,"html_url":"https://github.com/pfultz2/Pythy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FPythy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FPythy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FPythy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfultz2%2FPythy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pfultz2","download_url":"https://codeload.github.com/pfultz2/Pythy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248566536,"owners_count":21125681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T12:51:33.452Z","updated_at":"2025-04-12T12:31:45.441Z","avatar_url":"https://github.com/pfultz2.png","language":"C","readme":"Pythy\n=====\n\nHaving it all now: Pythy syntax for C++11. \n\nOverview\n--------\n\nIn a [blog post](http://cpp-next.com/archive/2011/11/having-it-all-pythy-syntax/), David Abrahams discussed an improved function syntax based around polymorphic lambdas:\n```c++\n[]min(x, y)\n{ return x \u003c y ? x : y; }\n```\nThe pythy library implements this in C++11 using a macro like this:\n```c++\nPYTHY(min, x, y)\n( return x \u003c y ? x : y; )\n```\nInternally, it uses references for each of the parameters. To make each parameter const, the const keyword can be written:\n```c++\nPYTHY(min, const x, const y)\n( return x \u003c y ? x : y; )\n```\nIf mutablility needs to be forced, the `mutable` keyword can be used:\n```c++\nPYTHY(add, mutable x, y)\n(\n    x += y;\n)\n```\nReferences can't be used, since a reference is already being used internally. \n\nBy default, pythy functions decay their return value, just like lambdas; so they always return by value, However, the `pythy::ref` function can be used to return a reference:\n```c++\nPYTHY(first, r)\n(\n    return pythy::ref(*(begin(r)));\n)\n```\n\nThis macro is much more powerful than using the simple `RETURNS` macro, like below: \n```c++\n#define RETURNS(...) -\u003e decltype(__VA_ARGS__) { return (__VA_ARGS__); }\ntemplate\u003cclass T, class U\u003e\nauto min(T x, U y) RETURNS(x \u003c y ? x : y)\n```\nFor example, a multi-statement function can be written:\n```c++\nPYTHY(first, r)\n(\n    if (r.empty()) throw \"The range is empty\";\n    return pythy::ref(*(begin(r)));\n)\n```\nOr a function that returns lambda can be written:\n```c++\nPYTHY(equal_to, x)\n(\n    return [=](decltype(x) y) { return x == y; }\n)\n```\nWhich can not be done using the `RETURNS` macro.\n\nImplementation\n--------------\n\nThis is implemented using a templated lambda. Lambdas can't be templated locally(and neither can classes), but we can make a lambda depend on a template parameter. So, if we define a lambda inside a templated class, like this:\n```c++\ntemplate\u003cclass T0, class T1\u003e\nstruct min_t\n{\n    constexpr static auto f = [](T0 x, T1 y){ return x \u003c y ? x : y; }; \n};\n```\nThis won't work, because a lambda closure(even if its non-capturing) is not a constexpr. However, using a trick(as suggested by Richard Smith from clang) we can initialize it as a null pointer:\n```c++\ntemplate\u003ctypename T\u003e \ntypename std::remove_reference\u003cT\u003e::type *addr(T \u0026\u0026t) \n{ \n    return \u0026t; \n}\ntemplate\u003cclass T0, class T1\u003e\nstruct min_t\n{\n    constexpr static auto *f = false ? addr([](T0 x, T1 y){ return x \u003c y ? x : y; }) : nullptr; \n};\n```\nThen when we want to call our function, we can do this:\n```c++\ntemplate\u003cclass T0, class T1\u003e\nauto min(T0 x, T1 x) RETURNS((*min_t\u003cT0, T1\u003e::f)(x, y))\n```\nIt appears that we are derefencing a null pointer. Remember in C++ when dereferencing a null pointer, undefined behavior occurs when there is an lvalue-to-rvalue conversion. However, since a non-capturing lambda closure is almost always implemented as an object with no members, undefined behavior never occurs, since it won't access any of its members. Its highly unlikely that a non-capturing lambda closure could be implemented another way since it must be convertible to a function pointer. But the library does statically assert that the closure object is empty to avoid any possible undefined behavior.\n\nRequirements\n------------\n\nThis requires a compiler that supports `auto`, `constexpr` and lambdas. It also relies on boost. For some compilers the `-DBOOST_PP_VARIADICS=1` must be passed into the compiler. ","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfultz2%2Fpythy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpfultz2%2Fpythy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfultz2%2Fpythy/lists"}