繁体   English   中英

将变量分配给 function 中的类型,我怎样才能让类型本身成为描述变量 output 类型的输入? : Swift 5

[英]Assigning variable to a type in a function, how can I have the type itself be an input that will describe the type of a variable output? : Swift 5

我制作了一个包含数据、偏移量和读取方法的文件读取结构(不知何故 fread() 让我感到困惑)。

我已经让它工作了,现在想在其中实现一个方法,它将采用 nxm 矩阵项和 output 值矩阵。 (类似于 matlab 中的 fread(FileID, [ nm ], "(datatype)"))。

这是我的想法

// should be able to handle all sorts of datatypes and output n by m matrix.
    mutating func matRead( dim : [[Int]], dtype : Int ){
        if dim.count != 2{
            fatalError("Dimensions dont match \"n by m\" in matRead")
        }
        // make sure to preallocate with zeros.
        
        var mat_Out : typecast[dtype][2].self = []
        
    }

我有一个看起来如此的类型转换字典

// typecast dictionary key : [ array_type, byte, element_type ]
let typecast : [Int16:[Any]] = [ 1: [ [UInt8].self  , 1, "uint8"],
                              2: [ [UInt16].self , 2, "uint16"],  // use .self to reference data type itself.
                              3: [ [UInt32].self , 4, "uint32"],
                              4: [ [Int8].self   , 1, "int8"  ],
                              5: [ [Int16].self  , 2, "int16" ],
                              6: [ [Int32].self  , 4, "int32" ],
                              7: [ [Float32].self, 4, "float32"],
                              8: [ [Float64].self, 8, "float64"],
                              12:[ [Int32].self  , 4, "int32" ]   ]

这是问题: matRead() function 的第 8 行不起作用。 Swift 不明白我正在尝试使用类型转换字典将 output 矩阵分配给新的数组类型。 我也试过 "as" var mat_Out: Any = [] as typecast[dtype][0] ,同样的错误(Swift 编译器认为我的意思是把括号放在外面)。

或者,我可以 go 很长的路要走,然后根据字符串值手动进行类型转换(已经必须这样做:参见下面的 fread 结构代码),但是如果有另一种方法,它将非常节省时间。


下面的 FileReading 结构(检查计数的冗余使用,但我没有清理它)

struct fRead {
    var off : Int = 0
    let data : Data
    
    mutating func resetOffsetToZero() {
        off = 0
    }
    
    mutating func setOffset( _ to : Int ) {
        off.self = to
    }
    mutating func moveOffset( _ by : Int) {
        off.self += by
    }
    func getOffset() -> Int {
        return off
    }
    // reading without specified number of elements defaults to 1.
    // these mutating funcs vary only in their output type and byte offset size.
    mutating func int32Read(count : Int = 1) -> [Int32] {
        var int32out : [Int32] = []
        if count > 1 {
            for i in 0...count-1 {
                int32out.append( Int32( data.subdata(in: off + i * 4..<(off + (i + 1) * 4) ).withUnsafeBytes{ $0.load(as: Int32.self )} ))
            }
            off += count * 4
        }
        else if count == 1 {
            int32out =  [ Int32( data.subdata(in: off..<(off+4) ).withUnsafeBytes{ $0.load(as: Int32.self )} )]
            off += 4
        }
        else if count == 0 {
            return []
        } else if count < 0{
            print("Warning, fReadint32Read( count : Int = 1) called with a negative count, returning empty array.")
        }
        return int32out
    }
    
    mutating func int16Read(count : Int = 1) -> [Int16] {
        var int16out : [Int16] = []
        if count > 1 {
            for i in 0...count-1 {
                int16out.append( data.subdata(in: off + i * 2..<(off + (i + 1) * 2) ).withUnsafeBytes{ $0.load(as: Int16.self )} )
            }
            off += count * 2
        }
        else if count == 1 {
            int16out =  [ data.subdata(in: off..<(off+2) ).withUnsafeBytes{ $0.load(as: Int16.self )} ]
            off += 2
        }
        else if count == 0 {
            return []
        } else if count < 0 {
            print("Warning, fRead.int16Read( count : Int = 1) called with a negative count, returning empty array.")
        }
        return int16out
    }
    
    mutating func float64Read(count : Int = 1) -> [Float64] {
        var float64out : [Float64] = []
        if count > 1 {
            for i in 0...count-1 {
                float64out.append( data.subdata(in: off + i * 8..<(off + (i + 1) * 8) ).withUnsafeBytes{ $0.load(as: Float64.self )} )
            }
            off += count * 8
        }
        else if count == 1 {
            float64out =  [ data.subdata(in: off..<(off+8) ).withUnsafeBytes{ $0.load(as: Float64.self )} ]
            off += 8
        }
        else if count == 0 {
            return []
        } else if count < 0 {
            print("Warning, fRead.int16Read( count : Int = 1) called with a negative count, returning empty array.")
        }
        return float64out
    }
    
    mutating func uint32Read(count : Int = 1) -> [UInt32] {
        var uint32out : [UInt32] = []
        if count > 1 {
            for i in 0...count-1 {
                uint32out.append( data.subdata(in: off + i * 4..<(off + (i + 1) * 4) ).withUnsafeBytes{ $0.load(as: UInt32.self )} )
            }
            off += count * 4
        }
        else if count == 1 {
            uint32out =  [ data.subdata(in: off..<(off+4) ).withUnsafeBytes{ $0.load(as: UInt32.self )} ]
            off += 4
        }
        else if count == 0 {
            return []
        } else if count < 0 {
            print("Warning, fRead.int16Read( count : Int = 1) called with a negative count, returning empty array.")
        }
        return uint32out
    }
    
    mutating func int64Read(count : Int = 1) -> [Int64] {
        var int64out : [Int64] = []
        if count > 1 {
            for i in 0...count-1 {
                int64out.append( Int64( data.subdata(in: off + i * 4..<(off + (i + 1) * 8) ).withUnsafeBytes{ $0.load(as: Int64.self )} ))
            }
            off += count * 8
        }
        else if count == 1 {
            int64out =  [ Int64( data.subdata(in: off..<(off+8) ).withUnsafeBytes{ $0.load(as: Int64.self )} )]
            off += 8
        }
        else if count == 0 {
            return []
        } else if count < 0{
            print("Warning, fReadint64Read( count : Int = 1) called with a negative count, returning empty array.")
        }
        return int64out
    }
    // should be able to handle all sorts of datatypes and output n by m matrix.
    mutating func matRead( dim : [[Int]], dtype : Int ){
        if dim.count != 2{
            fatalError("Dimensions dont match \"n by m\" in matRead")
        }
        // make sure to preallocate with zeros.
        
        var mat_Out : Any = [] as typecast[dtype][0]
        
    }
}

// I only discovered afterwards that 0...0 range works! So all the testing for  ==1 , == 0 wasn't necessary

通用解决方案不是最好的方法吗? 以下是元素为 integer 的通用版本,因此浮点数( BinaryFloatingPoint )需要类似的 function 。

mutating func matRead<T: BinaryInteger>(count: Int = 1) -> [T] {
    var intOut : [T] = []
    let width = T().bitWidth / 8
    if count > 1 {
        for i in 0...count-1 {
            intOut.append( T( data.subdata(in: off + i * 4..<(off + (i + 1) * width) ).withUnsafeBytes{ $0.load(as: T.self )} ))
        }
        off += count * width
    }
    else if count == 1 {
        intOut =  [ T( data.subdata(in: off..<(off+width) ).withUnsafeBytes{ $0.load(as: T.self )} )]
        off += width
    }
    else if count == 0 {
        return []
    } else if count < 0{
        print("Warning, fReadint64Read( count : Int = 1) called with a negative count, returning empty array.")
    }
    return intOut
}

请注意,上面的代码中有一个“错误”,我不确定在i * 4..<(off + (i + 1)中用什么替换 4,因为您在函数之间使用的数字如此不一致。我想它应该是width / 2但我留给你更新那部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM