Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 526 Vote(s) - 3.47 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Default value for optional generic parameter in Swift function

#1
Is it possible to give an optional generic parameter a default value?

I'm trying to do something like this:

func addChannel<T>(name: String, data: T? = nil) -> Channel {

}

let myChannel = addChannel("myChannelName")

But I'm getting an error saying

`Argument for generic parameter 'T' could not be inferred`

Is it just a case of what I'm trying to do being impossible?
Reply

#2
I encountered a similar issue while defining a complex function with a large number of generics, for which overloading would have resulted in an unmanageable number of variations. Here is the code:

```
struct Channel{
//Your code here
}

class ChannelManager{
static let typedNil : Int? = nil //<--- This is what eliminates the error "Argument for generic parameter 'T' could not be inferred"

public static func addChannel<T>(name: String, data: T? = typedNil) -> Channel{
//Your code here
return Channel() //To demonstrate that code compiles
}
}
```

By declaring ```typedNil``` in this manner and using it as a default parameter, the default still is ```nil``` as expected, but the compiler sees it as a ```nil``` ```int``` and so is able to infer the type, avoiding the requirement of adding additional protocol conformance to existing types, or requiring overloads. Note that declaring ```typedNil``` as ```static```, otherwise compilation will fail with the error "Cannot use instance member 'typedNil' as a default parameter."
Reply

#3
I use a combination of the existing answers so that I can both call the function without the optional argument and avoid implementing the function twice.

```swift
func addChannel(name: String) -> Channel {
addChannel(name: name, data: Optional<Any>.nil)
}
func addChannel<T>(name: String, data: T? = nil) -> Channel {
...
}
```

As mentioned above you should avoid `Any`. In my case I know that `T` is an `Encodable` so I use this:

```swift
struct DefaultEncodable: Encodable {}

func function1(name: String) {
addChannel(name: name, data: Optional<DefaultEncodable>.nil)
}
func function1<T: Encodable>(name: String, data: T? = nil) {
...
}

```
Reply

#4
I ran into the same problem. While not being able to use the generic default traditionally — leaving the argument out completely — I prefer the below to implementing overloads:

let myChannel=addChannel("myChannelName", data: Optional<Any>.none)
Reply

#5
It's impossible in the way you've done it. Given just the code above, what type is `T`? The compiler, as it says, can't figure it out (neither can I, and I assume you couldn't either because the data's not there).

The solution to the specific question is to overload rather than use defaults:

func addChannel<T>(name: String, data: T?) -> Channel { ... }

func addChannel(name: String) -> Channel { ... }

let myChannel = addChannel("myChannelName")

But it raises the question of what you're doing here. You would think that `Channel` should be `Channel<T>`. Otherwise, what are you doing with `data`? Without resorting to `Any` (which you should strongly avoid), it's hard to see how your function can do anything but ignore `data`.

With `Channel<T>` you can just use a default, but you'd have to provide the type:

func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
let myChannel: Channel<Int> = addChannel("myChannelName")

Otherwise the compiler wouldn't know what kind of channel you're making.

(UPDATE ~ Swift 5.2)

Sometimes you'd like a default type for `T`. You can do that with an overload. For example, you might want the default type to be `Never`. In that case, you would add an overload like this:

func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
func addChannel(name: String) -> Channel<Never> {
addChannel(name: name, data: Optional<Never>.none)
}

With that, you can have a simpler call:

let myChannel = addChannel(name: "myChannelName") // Channel<Never>
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through