Skip to content

Commit

Permalink
Updating README and CHANGELOG
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed Jan 10, 2024
1 parent 3b09c37 commit 62ce159
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 34 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## Unreleased

### Changed
- `BlockUtil.h`: `makeBlock` is deprecated in ObjectiveC++. Modern versions of Clang allow conversions from lambdas to block directly doing essentially what `makeBlock` was doing. Note that it is still available and necessary in C++.
- `BoxUtil.h`: boxing now detects comparability and enables `compare:` not just via presence of operator `<=>` but also when only operators `<`, `==`, `<=` etc. are present.

## [2.3] - 2024-01-09

### Added
Expand Down
67 changes: 33 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ An ever-growing collection of utilities to make coding on Apple platforms in C++
<!-- TOC depthfrom:2 -->

- [What's included?](#whats-included)
- [BlockUtil.h](#blockutilh)
- [CoDispatch.h](#codispatchh)
- [BoxUtil.h](#boxutilh)
- [NSObjectUtil.h](#nsobjectutilh)
- [NSStringUtil.h](#nsstringutilh)
- [NSNumberUtil.h](#nsnumberutilh)
- [XCTestUtil.h](#xctestutilh)
- [BlockUtil.h](#blockutilh)
- [General notes](#general-notes)

<!-- /TOC -->
Expand All @@ -24,39 +24,6 @@ The library is a collection of mostly independent header files. There is nothing

The headers are as follows:

### `BlockUtil.h` ###

Allows clean and safe usage of C++ lambdas instead of ObjectiveC blocks (which are confusingly also available
in pure C++ on Apple platforms as an extension).

Why not use blocks? Blocks capture any variable mentioned in them automatically which
causes no end of trouble with inadvertent capture and circular references. The most
common one is to accidentally capture `self` in a block. There is no protection in
ObjectiveC - you have to manually inspect code to ensure this doesn't happen.
Add in code maintenance, copy/paste and you are almost guaranteed to have bugs.
Even if you have no bugs your block code is likely littered with strongSelf
nonsense making it harder to understand.

C++ lambdas force you to explicitly specify what you capture, removing this whole problem.
Unfortunately lambdas cannot be used as blocks. This header provides utility functions
to fix this.
The intended usage is

```objc++
[foo doBar:makeBlock([weakSelf = makeWeak(self)] () {
auto self = makeStrong(weakSelf);
if (!self)
return;
[self doSomething];
}];
```

Note that since in C++ code `self` isn't anything special we can use it as variable name
for, well, actual self.

Since blocks are supported even in plain C++ by Apple's clang compiler as an extension you can
use this facility both from plain C++ (.cpp) and ObjectiveC++ (.mm) files.

### `CoDispatch.h` ###

Allows you to use **asynchronous** C++ coroutines that execute on GCD dispatch queues. Yes there is [this library](https://github.com/alibaba/coobjc) but it is big, targeting Swift and ObjectiveC rather than C++/\[Objective\]C++ and has a library to integrate with. It also has more features, of course. Here you get basic powerful C++ coroutine support in a single not very large (~800 loc) header.
Expand Down Expand Up @@ -241,6 +208,38 @@ That, in the case of failure, try to obtain description using the following meth

Thus if an object is printable using the typical means those will be automatically used. You can also make your own objects printable using either of the means above. The `testDescription` approach specifically exists to allow you to print something different for tests than in normal code.

### `BlockUtil.h` ###

> ℹ️️ Modern versions of Clang allow conversions of lambdas to blocks directly in **ObjectiveC++** (but not in plain C++). Thus `makeBlock` call described below is no longer necessary in ObjectiveC++ and is deprecated. It is still available in C++.
Allows clean and safe usage of C++ lambdas instead of ObjectiveC blocks which are also available
in pure C++ on Apple platforms as an extension.

Why not use blocks? Blocks capture any variable mentioned in them automatically which
causes no end of trouble with inadvertent capture and circular references. The most
common one is to accidentally capture `self` in a block. There is no protection in
ObjectiveC - you have to manually inspect code to ensure this doesn't happen.
Add in code maintenance, copy/paste and you are almost guaranteed to have bugs.
Even if you have no bugs your block code is likely littered with strongSelf
nonsense making it harder to understand.

C++ lambdas force you to explicitly specify what you capture, removing this whole problem.
Unfortunately lambdas cannot be used as blocks. This header provides utility functions
to fix this.
The intended usage is something like this

```objc++
dispatch_async(makeBlock([weakSelf = makeWeak(self)] () {
auto self = makeStrong(weakSelf);
if (!self)
return;
[self doSomething];
}));
```

> ℹ️️ Note that in C++ the block returned from `makeBlock` needs to be released at some point via `Block_release` - there is no ARC to handle it for you.
### General notes ###

For all comparators `nil`s are handled properly. A `nil` is equal to `nil` and is less than any non-`nil` object.
Expand Down

0 comments on commit 62ce159

Please sign in to comment.