[Pitch] UnsafePointer.advanced(to:)

It won't happen for Swift 4, but I think we should eventually have APIs like:

extension UnsafePointer {
    func advanced<T>(to keyPath: KeyPath<Pointee, T>) -> UnsafePointer<T>?
}

If keyPath referred to a stored property directly inside the value, this would return a pointer to that property. If keyPath is a computed property, or the property is not stored relative to the pointer (e.g. an object or indirect pointer), it returns nil.

My most immediate use case is for working with MIDI structures, which have an inline byte buffer, but I suspect there will be other uses as well.

···

--
Brent Royal-Gordon
Sent from my iPhone

1 Like

Why would this be an extension on UnsafePointer and not KeyPath?

···

On Tue, Jun 6, 2017 at 10:28 Brent Royal-Gordon via swift-evolution < swift-evolution@swift.org> wrote:

It won't happen for Swift 4, but I think we should eventually have APIs
like:

extension UnsafePointer {
    func advanced<T>(to keyPath: KeyPath<Pointee, T>) -> UnsafePointer<T>?
}

If keyPath referred to a stored property directly inside the value, this
would return a pointer to that property. If keyPath is a computed property,
or the property is not stored relative to the pointer (e.g. an object or
indirect pointer), it returns nil.

My most immediate use case is for working with MIDI structures, which have
an inline byte buffer, but I suspect there will be other uses as well.

--
Brent Royal-Gordon
Sent from my iPhone
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1. I can't come up with a name as good as `advanced(to:)` that would be attached to the key path. I use `advance(_:)` in the other two reasons below, but I don't think it's nearly as clear about what it's doing to the pointer.

2. Passing the pointer as the parameter would encourage use of `&`, which would be invalid.

  (\CGRect.origin.y).advance(&myRect) // Pointer might be to a temporary
  (&myRect).advanced(to: \.origin.y) // Rejected during compilation because & is not allowed there

3. Passing the key path as a parameter improves the code's appearance when you specify the key path in the expression.

  myRectPtr.advanced(to: \.origin.y)
  (\CGRect.origin.y).advance(myRectPtr) // Requires explicit type name and extra parentheses

···

On Jun 6, 2017, at 9:06 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Why would this be an extension on UnsafePointer and not KeyPath?

--
Brent Royal-Gordon
Architechies

1 Like

IIUC this has nothing to do with "advancing", though. Maybe "applying"
or even "map" would be a better name?

···

on Tue Jun 06 2017, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

On Jun 6, 2017, at 9:06 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Why would this be an extension on UnsafePointer and not KeyPath?

1. I can't come up with a name as good as `advanced(to:)` that would
be attached to the key path. I use `advance(_:)` in the other two
reasons below, but I don't think it's nearly as clear about what it's
doing to the pointer.

2. Passing the pointer as the parameter would encourage use of `&`, which would be invalid.

  (\CGRect.origin.y).advance(&myRect) // Pointer might be to a temporary
  (&myRect).advanced(to: \.origin.y) // Rejected during compilation because & is not allowed
there

3. Passing the key path as a parameter improves the code's appearance when you specify the key path
in the expression.

  myRectPtr.advanced(to: \.origin.y)
  (\CGRect.origin.y).advance(myRectPtr) // Requires explicit type name and extra parentheses

--
-Dave

Why would this be an extension on UnsafePointer and not KeyPath?

1. I can't come up with a name as good as `advanced(to:)` that would
be attached to the key path. I use `advance(_:)` in the other two
reasons below, but I don't think it's nearly as clear about what it's
doing to the pointer.

2. Passing the pointer as the parameter would encourage use of `&`, which would be invalid.

  (\CGRect.origin.y).advance(&myRect) // Pointer might be to a temporary
  (&myRect).advanced(to: \.origin.y) // Rejected during compilation because & is not allowed
there

3. Passing the key path as a parameter improves the code's appearance when you specify the key path
in the expression.

  myRectPtr.advanced(to: \.origin.y)
  (\CGRect.origin.y).advance(myRectPtr) // Requires explicit type name and extra parentheses

IIUC this has nothing to do with "advancing", though. Maybe "applying"
or even "map" would be a better name?

How about `offset`?

···

On Jun 6, 2017, at 12:56 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Tue Jun 06 2017, Brent Royal-Gordon <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 6, 2017, at 9:06 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

It's not an offset because the result is a different type of thing than the source

···

Sent from my moss-covered three-handled family gradunza

On Jun 6, 2017, at 1:09 PM, Hooman Mehr <hooman@mac.com> wrote:

On Jun 6, 2017, at 12:56 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Tue Jun 06 2017, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

On Jun 6, 2017, at 9:06 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Why would this be an extension on UnsafePointer and not KeyPath?

1. I can't come up with a name as good as `advanced(to:)` that would
be attached to the key path. I use `advance(_:)` in the other two
reasons below, but I don't think it's nearly as clear about what it's
doing to the pointer.

2. Passing the pointer as the parameter would encourage use of `&`, which would be invalid.

  (\CGRect.origin.y).advance(&myRect) // Pointer might be to a temporary
  (&myRect).advanced(to: \.origin.y) // Rejected during compilation because & is not allowed
there

3. Passing the key path as a parameter improves the code's appearance when you specify the key path
in the expression.

  myRectPtr.advanced(to: \.origin.y)
  (\CGRect.origin.y).advance(myRectPtr) // Requires explicit type name and extra parentheses

IIUC this has nothing to do with "advancing", though. Maybe "applying"
or even "map" would be a better name?

How about `offset`?

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I just ran into a use case for this as well, though I agree with others in this thread that "advanced" may not be the best name. A simple subscript works great

extension UnsafePointer {
    
    subscript<T>(_ keyPath: KeyPath<Pointee, T>) -> UnsafePointer<T> {
        let raw = UnsafeRawPointer(self)
        // If a key path is not directly-addressable I consider it programmer error
        let offset = MemoryLayout<Pointee>.offset(of: keyPath)!
        return raw.advanced(by: offset).assumingMemoryBound(to: T.self)
    }
    
}
1 Like