Which types in Swift are considered trivial types and is there a Protocol, or Protocol composition, to restrict a generate parameter to only trivial types.
Consider a generic function for writing values into a raw buffer:
The documentation for storeBytes<T>(of: T, toByteOffset: Int, as: T.Type) states that T must be a trivial type. However, the compiler doesn't seem to complain if I do something like this:
class Style {
var color = NSColor.red
var font = NSFont.labelFont(ofSize:11)
}
let style = Style()
write(style)
Style isn't something I'd consider to be a trivial type that .storeBytes can properly store, yet there's no error.
So what would be an appropriate constraint on write<T>(_ value:T) where T... such that only trivial types are allowed?
Yeah, I know @Andrew_Trick is also interested in exposing a proper Trivial layout type constraint that could be used in generics as well. That would allow for load and storeBytes to work reliably with unaligned addresses too.
In the meantime, you can make your generic function require that T conform to an empty protocol of your own devising, and than retroactively conform the types you want to support to that protocol.
Agreed, but of the existing protocols related to "numbers", which ones would be best to use to support:
All Integer Types
All Float Types
All Bool Types
Are BinaryInteger and FloatingPoint the best options for the first two? What about for Bool or would it be better to just have a typed version of write(_ value:Bool) for that?
Rather than enter the numeric protocol labyrinth, I would just do this on concrete types. Adding a conformance is simple, and you don’t need to add them all up front; you can just ‘fault’ them in as you need them.
Oh, and btw, despite my example above, I’m not totally comfortable with conforming Int to this protocol. Remember that Int is pointer sized and, conceptually at least, the sending and receiving processes could have different pointer sizes [1].
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
[1] On macOS this can’t happen because 32-bit macOS code runs on the old runtime, and Swift requires the modern runtime.
I mean, it's not really important, but you could keep them like that. There's also Float80 (everywhere except Windows, I think?) and we'll probably get a Float16 at some point.
As that thread says, Float32/64 were supposed to be the "true" names and Float/Double were going to be aliases. Like I said, not important - just an interesting bit of history.
There have been requests for an AnyValue automatic protocol, that is a counter to AnyObject. Your idea would be an AnyTrival automatic protocol (and would refine AnyValue?).
Any... would be the wrong prefix to use. That tends to be used to signify a type-erased supertype into which you can assign any of the subtypes, which isn't relevant here. The request is for a generic constraint (even if, coincidentally, you could also use it as en existential protocol).
You're thinking when we could (still can?) use "class" to specify a class constraint:
protocol ForClassesOnly1: AnyObject {} // we use nowadays for...
protocol ForClassesOnly2: class {} // ...this, the old(?) syntax.
So now, you would prefer something like:
protocol ForValueTypesOnly1: any !class // once "any" is a keyword
protocol ForValueTypesOnly2: any value // two new keywords
protocol ForTrivialTypesOnly: any trivial value // three new keywords
No – AnyObject serves two purposes: as a constraint, and as a type-erased container for any class instance. The Any... part comes from the latter use. That latter use doesn't apply to trivial types, so I am saying it would be inappropriate for the constraint to be AnyTrivial i.e. it should just be Trivial.
While that is typically true, there are other layout constraints which could act as a kind-of "supertype" (or superset, really) of trivial types. For example, compiler also supports exact-size and maximum-size trivial constraints. Would we do AnyTrivial(64)?
Apparently you can use them in @_specialize, and they actually work: