2016-10-21 5 views
1

CollectionのSubSequenceをStringに変換したいと思っています。たとえば、この関数はコレクションの最初の2バイトを収集し、それをStringに変換します。CollectionのサブシーケンスをStringに変換する

func convert<T: Collection>(_ c: T) -> String 
    where T.Iterator.Element == UInt8 
{ 
    let start = c.startIndex 
    let end = c.index(after: start) 
    return String(bytes: c[start ... end], encoding: String.Encoding.utf8)! 
} 

これは、このエラーにつながる:私はここで何をしないのです

error: ambiguous reference to member 'subscript' 
     return String(bytes: c[start ... end], encoding: String.Encoding.utf8)! 
          ~^~~~~~~~~~~~~~~ 
Swift.Collection:167:12: note: found this candidate 
    public subscript(position: Self.Index) -> Self.Iterator.Element { get } 
     ^
Swift.Collection:189:12: note: found this candidate 
    public subscript(bounds: Range<Self.Index>) -> Self.SubSequence { get } 
     ^
Swift.Collection:25:12: note: found this candidate 
    public subscript(bounds: Range<Self.Index>) -> Slice<Self> { get } 
     ^
Swift.IndexableBase:54:12: note: found this candidate 
    public subscript(position: Self.Index) -> Self._Element { get } 
     ^
Swift.IndexableBase:63:12: note: found this candidate 
    public subscript(bounds: Range<Self.Index>) -> Self.SubSequence { get } 
     ^
Swift.Indexable:23:12: note: found this candidate 
    public subscript(bounds: ClosedRange<Self.Index>) -> Self.SubSequence { get } 
     ^
Swift.Indexable:23:12: note: found this candidate 
    public subscript(bounds: CountableRange<Self.Index>) -> Self.SubSequence { get } 
     ^
Swift.Indexable:45:12: note: found this candidate 
    public subscript(bounds: CountableClosedRange<Self.Index>) -> Self.SubSequence { get } 

? :-)

+1

本文を 'return String(bytes:c.prefix(2)、encoding:.utf8)! 'に簡略化することができます。 –

+0

確かに。このエラーを示す簡単な例でした。 – Etan

答えて

3

現在、CollectionSubSequenceは、associatedtypeの制限が原因で、コレクション自体と同じ要素タイプを持つことが保証されていません。

実際、SE-0142: Permit where clauses to constrain associated typesの動機の1つは、この関係を実行する制約associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Elementを許可することです。

あなたが最初の場所でT.Iterator.Element == UInt8制約を利用していないとして、この特定のケースでは、あなたの代わりに(感謝@MartinRを)T.SubSequence.Iterator.Elementを制約することができますが:あなたも、より一般的なケースでは

func convert<T: Collection>(_ c: T) -> String 
    where T.SubSequence.Iterator.Element == UInt8 { 

    let start = c.startIndex 
    let end = c.index(after: start) 

    // please consider handling the case where String(bytes:encoding:) returns nil. 
    return String(bytes: c[start ... end], encoding: String.Encoding.utf8)! 
} 

(指定されたタイプに制限されたT.Iterator.Elementが必要な場合は、追加の制約としてT.SubSequence.Iterator.Element == T.Iterator.Elementを追加することをお勧めします)。

+1

同じものを投稿しようとしていました:)単一の制約 'T.SubSequence.Iterator.Element == UInt8'で十分でしょう。 –

+0

@MartinRああ、あなたは大丈夫です - 指摘のおかげで:) – Hamish

+0

これは実際には両方の制約が必要な単純化された例でした。両方のケースの説明をありがとう! – Etan

関連する問題