📝
[Swift] オーバーロード選択クイズ10問
はじめに
Swiftには関数のオーバーロード機能があります。
ある呼び出しについて、有効なオーバーロードが複数ある場合、どのオーバーロードが選択されるかはコンパイラの型推論器に定められたルールによって決まっています。
以下の10個のプログラムにおいて、それぞれどの関数が選択される(もしくは、何が出力される)でしょうか?
正解とする環境
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
実行コマンド
swift Source.swift
-enable-upcoming-feature
なし
第1問
func f(_ a: Int?) { print("Int?") }
func f(_ a: Any) { print("Any") }
let a: Int = 1
f(a)
答え
Any
第2問
struct A: Hashable {}
func f(_ a: Any) { print("Any") }
func f(_ a: AnyHashable) { print("AnyHashable") }
let a: A = A()
f(a)
答え
Any
第3問
func a(_ b: Int) {}
var a = 0
func f(_ a: (Int) -> Void) {
print("func")
}
func f(_ a: Int) {
print("var")
}
f(a)
答え
var
第4問
func f(_ a: [Int]?) { print("[Int]?") }
func f(_ a: [Int?]) { print("[Int?]") }
let a: [Int] = [1, 2, 3]
f(a)
答え
[Int]?
第5問
import Foundation
func f(_ a: CGFloat) { print("CGFloat") }
func f(_ a: Double?) { print("Double?") }
let a: Double = 10.0
f(a)
答え
Double?
第6問
func f(_ a: UnsafePointer<Int>) { print("UnsafePointer<Int>") }
func f(_ a: [Int]?) { print("[Int]?") }
let a: [Int] = [1, 2, 3]
f(a)
答え
UnsafePointer<Int>
第7問
func f(_ a: Int) { print("Int") }
func f(_ a: Int?) { print("Int?") }
var a: Int! = 1
f(a)
答え
Int?
第8問
func f(
_ a: (() -> Void)? = nil,
_ b: (() -> Void)? = nil
) {
if a != nil { print("forward") }
if b != nil { print("backward") }
}
f { }
答え
backward
Swift 6.0もしくは-enable-upcoming-feature ForwardTrailingClosures
で
forward
第9問
func h(_ a: () async -> Void) {
print("async")
}
func h(_ a: () -> Void) {
print("sync")
}
h { }
答え
sync
第10問
func f() { print("sync") }
@_disfavoredOverload
func f() async { print("async") }
func g() async {
f()
}
await g()
答え
func f() async
が選択される (awaitがないのでコンパイルエラー)
おまけ
func h(_ a: () async -> Void) async {
print("async")
}
func h(_ a: () -> Void) {
print("sync")
}
func g() async {
await h { }
}
await g()
答え
sync
バグではないのですが、奇妙で直感に反する挙動だと感じたのでおまけにしました。
forumでも聞いてみました
最後に
何問正解できましたか?
オーバーロード選択のルールについて詳しくは以下の記事を参照
Discussion