2017-09-07 8 views
1

戻り値の型で関数をオーバーロードしようとしています。戻り値の型は、別の汎用関数の型制約からのソースです。型制約のある汎用関数の型を使用して戻り値の型をオーバーロードする

私は、プロトコルの制約により、すべてのケース(Int、String)を提供できると考えました。遊び場で動く小さなテストケースです。使用されるべき候補機能を推測するように、コンパイラのための十分な情報が

protocol Gettable {} 
extension Int: Gettable {} 
extension String: Gettable {} 

struct Test { 
    static func get() -> Int { 
    return 1 
    } 
    static func get() -> String { 
    return "1" 
    } 
} 

func getOne<T: Gettable>(_: T.Type) { 
    let value: T = Test.get() 
} 

getOne(Int.self) 
getOne(String.self) 

これは、次のエラー

error: test.playground:11:23: error: no 'get' candidates produce the expected contextual result type 'T' 
    let value: T = Test.get() 
        ^

test.playground:11:23: note: overloads for 'get' exist with these result types: Int, String 
    let value: T = Test.get() 
        ^

生成ありませんか?

+2

これは、迅速なジェネリックスの仕組みではありません。 [間違った特殊なジェネリック関数が間接呼び出しからSwift 3で呼び出されるようになる](https://stackoverflow.com/q/41980001/2976878)と比較してください。コンパイラは、デフォルトでは、ジェネリック関数のプレースホルダを満たすために使用されるタイプのセットごとに特別な実装を発行しません。 'Test.get'のオーバーロード解決は' getOne'自体の内部で起こります。だから、コンパイラが 'T'を知っているのは、' Gettable'に制約されていて、 'String'か' Int'のどちらかを選ぶのに役立たないということだけです。 – Hamish

答えて

1

問題は、オーバーロードを伴うGettableのすべてのケースに対処したことをコンパイラが認識していないことです。

ここでコンパイラが必要とする分析の種類は実行できません。 Swiftは実行時に新しい型をレイアウトすることができます。これは特にジェネリックで使用されます。つまり、内部プロトコルとプライベートプロトコルを使用しても、コンパイル時の適合性の徹底的なテストは不可能です。

つまり、何らかのプロトコルに準拠するすべてのタイプに対して正しいタイプを返すオーバーロードがあることを確認できる制約を作成することはできません。

+0

これを回避するために、問題のコードをどのように設計する必要がありますか? @ハミッシュ – Pruthvikar

関連する問題