2014-11-03 13 views
5

Próbuję napisać ogólną funkcję wymagającą operacji zmiany bitów. Otrzymuję zachowanie, którego nie rozumiem. Oto prosta funkcja, która demonstruje problem.Przesuwanie bitów w szybkiej ogólnej funkcji

func testBytes<T: IntegerType>(bytesIn: [UInt8], inout dataOut: T){ 

let outputSize = sizeof(T) 
var temp: T = 0 
dataOut = 0 
temp = bytesIn[0] as T 
temp = temp << 1 

} 

Jeśli to zrobię, to ostatnia linia daje mi błąd w kodzie x "T nie jest zamienne do Int".

mogę zmienić ostatni wiersz temp = temp << (1 as T)

I wtedy błąd na tej linii zmienia się na „T nie jest wymienialny na Uint8”

ani jeden z tych komunikatów o błędach dla mnie sensu w tym kontekście . Czy jest coś, co mogę zrobić, aby umożliwić przenoszenie bitów na typ ogólny?

Odpowiedz

7

mam blog post on this topic że idzie do bardziej szczegółowo, ale zasadniczo istnieją trzy etapy:

  1. Załóż nowy protokół z operatorami Bitshift i konstruktor z UInt8:

    protocol BitshiftOperationsType { 
        func <<(lhs: Self, rhs: Self) -> Self 
        func >>(lhs: Self, rhs: Self) -> Self 
        init(_ val: UInt8) 
    } 
    
  2. Deklaracja zgodności z rozszerzeniem na każdym typie całkowitym - łatwa, ponieważ już implementują wszystko w postaci BitshiftOperationsType:

    extension Int : BitshiftOperationsType {} 
    extension Int8 : BitshiftOperationsType {} 
    extension Int16 : BitshiftOperationsType {} 
    extension Int32 : BitshiftOperationsType {} 
    extension Int64 : BitshiftOperationsType {} 
    extension UInt : BitshiftOperationsType {} 
    extension UInt8 : BitshiftOperationsType {} 
    extension UInt16 : BitshiftOperationsType {} 
    extension UInt32 : BitshiftOperationsType {} 
    extension UInt64 : BitshiftOperationsType {} 
    
  3. Dodaj rodzajowe ograniczenie tak T zgodny z nowym protokołem:

    func testBytes<T: IntegerType where T: BitshiftOperationsType>(bytesIn: [UInt8], inout dataOut: T){ 
        let outputSize = sizeof(T) 
        var temp: T = 0 
        dataOut = 0 
        temp = T(bytesIn[0]) 
        temp = temp << 1 
    } 
    

Dzięki Martin R. za poprawki dla bitu brutto miałem tutaj wcześniej!

+2

Przygotowałem podobną odpowiedź, ale byłeś szybszy :-). To, co zrobiłem, aby rozwiązać drugi problem, to dodanie do protokołu 'init (_ val: UInt8)'. Wszystkie typy (podpisane i niepodpisane) mają taki konstruktor, więc można wykonać konwersję z 'temp = T (bytesIn [0])' i potrzebna jest tylko jedna implementacja. –

+0

Świetna poprawka! Zaktualizowano odpowiedź tą zmianą. –

+0

Wielkie dzięki. Prawdopodobnie przedłożę wkrótce nowe pytanie dotyczące problemu, ponieważ generics może nie być elegancką odpowiedzią, której szukałem. – dustincarr

Powiązane problemy