2016-10-21 2 views
1

Я хотел бы преобразовать SubSequence коллекции в строку. Например, эта функция собирает первые два байта коллекции и преобразует ее в строку.Преобразование подпоследовательности коллекции в строку

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

Вы можете упростить тело, чтобы вернуть String (байты: c.prefix (2), encoding: .utf8)! ' –

+0

Конечно. Это был упрощенный пример, чтобы показать ошибку. – Etan

ответ

3

В настоящее время Collection «ы SubSequence не гарантируется, чтобы иметь один и тот же тип элемента, как и сама коллекция, что связано с ограничением associatedtype с.

Фактически, одна из мотиваций для SE-0142: Permit where clauses to constrain associated types заключается в том, чтобы разрешить ограничение associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element, которое обеспечило бы соблюдение этих отношений.

Хотя в данном конкретном случае, как вы не используя T.Iterator.Element == UInt8 ограничение в первую очередь, вы можете ограничить T.SubSequence.Iterator.Element вместо (спасибо @MartinR):

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

Смежные вопросы