gpt4 book ai didi

arrays - 如何为函数的通用数组参数(而不是其 Generator.Element)添加类型约束(协议(protocol)一致性)

转载 作者:搜寻专家 更新时间:2023-11-01 05:38:04 24 4
gpt4 key购买 nike

问题背景

我有一个问题是基于我自己尝试为以下线程的 OP 想要的行为产生令人满意的解决方法:

主题是(像 SO 的其他一些人一样...)试图模仿符合某些协议(protocol)的通用数组扩展。最近在这个线程中有一个关于这个主题的类似问题:


问题

我的问题涉及下一步。假设我们设法实现了对 Array 的某种通用扩展。 ,符合一些协议(protocol)蓝图,比如 MyProtocol .因此,从现在开始,假设 Array实例,对于某些类型的 Generator.Element (例如,对于 MyTypes ),现在已扩展并符合 MyProtocol .

然后,对于采用通用 Array 的函数(或者,具体地说,说 <U: _ArrayType ... ,或者可能是 RangeReplaceableCollectionType ...SequenceType ... )类型)作为参数,有没有办法向实际的泛型数组添加类型约束(U ), 而不仅仅是它的 Generator.Element类型? (所以不是 ... where Generator.Element.Type == SomeTypeConstraint )。

例子

我将尝试“实际”展示我的问题,以帮助说明我实际要问的内容。请注意,这是我为此目的能够构建的最大 MWE,如果它可能有点重,我深表歉意。

协议(protocol)(协议(protocol) MyTypes 用作类型 + 协议(protocol) MyProtocol 用于数组扩展):

/* Used as type constraint for Generator.Element */
protocol MyTypes {
var intValue: Int { get }
init(_ value: Int)
func *(lhs: Self, rhs: Self) -> Self
func +=(inout lhs: Self, rhs: Self)
}

extension Int : MyTypes { var intValue: Int { return self } }
extension Double : MyTypes { var intValue: Int { return Int(self) } }
/* Let's not extend 'Float' for now
extension Float : MyTypes { var intValue: Int { return Int(self) } } */

/* Used as extension to Array : blueprints for extension method
to Array where Generator.Element: are constrainted to MyTypes */
protocol MyProtocol {
//typealias T
func foo<T: MyTypes>(a: [T]) -> Int?
}

扩展Array通过 MyProtocol ;蓝图方法的实现:

extension Array : MyProtocol {
func foo<T: MyTypes>(a: [T]) -> Int? {
/* [T] is Self? proceed, otherwise return nil */
if let b = self.first {
if b is T && self.count == a.count {
var myMultSum: T = T(0)

for (i, sElem) in self.enumerate() {
myMultSum += (sElem as! T) * a[i]
}
return myMultSum.intValue
}
}
return nil
}
}

一些测试,我们对于一个函数,约束 Generator.ElementArray MyTypes 的参数,因此有点隐式断言只有符合 MyProtocol 的数组可以使用函数:

/* Tests */
let arr1d : [Double] = [1.0, 2.0, 3.0]
let arr2d : [Double] = [-3.0, -2.0, 1.0]

let arr1f : [Float] = [1.0, 2.0, 3.0]
let arr2f : [Float] = [-3.0, -2.0, 1.0]

func bar1<U: MyTypes> (arr1: [U], _ arr2: [U]) -> Int? {
return arr1.foo(arr2)
}
let myInt1d = bar1(arr1d, arr2d) // -4, OK

//let myInt1f = bar1(arr1f, arr2f)
/* Error: Cannot convert value of type '[Float]'
to expected argument type '[_]'

OK! Expected as 'Float' does not conform to MyTypes protocol */

现在我们已经到了我的问题的核心,一些我自己无法构建的东西:是否有任何可能的方法显式约束泛型数组,比如 U , 至 MyProtocol (对于哪些 Array 对于某些 Generator.Elements 已被约束)?我想做一些事情

func bar2<T: MyTypes, U: protocol<MyProtocol, _ArrayType> where U.Generator.Element == T> (arr1: U, _ arr2: U) -> Int? {

// OK, type 'U' behaves as an array type with elements 'T' (==MyTypes)
var a = arr1
var b = arr2
a.append(T(0))
b.append(T(0))

return a.foo(b)
/* Error: Cannot convert value of type 'U'
to expected argument type '[_]' */
}
let myInt2 = bar2(arr1d, arr2d)
  • 这可能吗,或许以不同的方式?

(随意编辑这个问题以改进它,我不是很精通在 SO 上提问的过程和最佳实践)

最佳答案

我设法修复了我的“做一些事情”提案工作,方法是:

  • <U: SequenceType ... 切换到 <U: _ArrayType ...(查看编辑历史记录),

  • 为了使用泛型数组(泛型 U)调用我的泛型数组扩展,在调用中显式初始化一个数组,显式告诉接收方调用者参数(泛型 U)的类型为 Array(使用 Array(...) 初始化器) ).

因此,我们可以为函数的通用数组参数添加类型约束(协议(protocol)一致性),使用问题中描述的通用数组扩展,然后采用以下协议(protocol)一致性方法:

func bar2<T: MyTypes, U: protocol<MyProtocol, _ArrayType> where U.Generator.Element == T> (arr1: U, _ arr2: U) -> Int? {

// OK, type U behaves as array type with elements T (=MyTypes)
var a = arr1
var b = arr2
a.append(T(2)) // add 2*7 to multsum
b.append(T(7))

return a.foo(Array(b))
/* Ok! */
}
let myInt2 = bar2(arr1d, arr2d) // -4+2*7 = 10, OK

关于arrays - 如何为函数的通用数组参数(而不是其 Generator.Element)添加类型约束(协议(protocol)一致性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34501723/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com