somu
(somu)
1
Hi,
Overview
- I have a generic struct
Box
- I have a function
func f1(newValue: T)
- I would like call 2 different implementations depending on whether T is String or not.
Questions:
- Is my attempt the correct way and does it guarantee to execute correctly all the time?
- Or what is the right way?
My Attempt:
I am not sure if this is the correct way.
struct Box<T> {
var value: T
func f1(newValue: T) {
print("non-string func value = \(newValue)")
}
}
extension Box where T == String {
func f1(newValue: T) {
print("String func value = \(newValue)")
}
}
Invoking
let b1 = Box(value: 10)
let b2 = Box(value: "aaa")
b1.f1(newValue: 25)
b2.f1(newValue: "bbb")
Output
non-string func value = 25
String func value = bbb
No, it's incorrect; there has been some discussion to warn users about. Box<String>.f1 simply shadows Box<T>.f1. This means that there is no dynamic dispatch. E.g.
func callF1<T>(_ box: Box<T>, _ newValue: T) {
box.f1(newValue: newValue) // Always call non-string f1
}
callF1(Box(value: 1), 2) // non-string
callF1(Box(value: "1"), "2") // non-string
You can simply check if T.self == String.self, though I'm not sure that's the fastest approach.
2 Likes
somu
(somu)
3
@filip-sakel Thanks a lot for that clarification.
Yeah T.self == String.self is one way to handle that String logic.
I think I will follow that approach if there is no better way.
1 Like
For more complex cases you can always create a protocol e.g. StringBox, that Box conditionally conforms to where T == String. Then, by conditionally casting self as? StringBox you can check for more complex values. For example, by having a conformance where T: StringProtocol you can customize your function based on whether your value conforms to a given protocol. However, I don’t know how efficient this is, you might have to benchmark against the aforementioned metatype comparison.
1 Like
somu
(somu)
5
Thanks a lot!! @filip-sakel
I will give it a try I think it should be fine for my use case