Trouble with operator overloading and inferred types in Swift -
literals
swift has couple of literals can used initialize different types without explicitly calling initializer. example,
let x = 5 // x int automatically infers x of type int. if specify type of variable else
let x: uint = 5 // x uint the compiler automatically understands 5 unsigned integer , respective uint initializer has called instead of int initializer.
the expressiblebyintegerliteral protocol
this possible types implement protocol expressiblebyintegerliteral. add protocol conformance own type:
/// represents range of characters in `string`. // /// purpose of type provide wrapper around `countableclosedrange` /// can initialized both range , **integer literal**. struct textrange: expressiblebyintegerliteral { let range: countableclosedrange<int> var lowerbound: int { return range.lowerbound } var upperbound: int { return range.upperbound } init(_ range: countableclosedrange<int>) { self.range = range } // initializer adds protocol conformance: init(integerliteral value: int) { self.range = value...value } } with definition can write:
let x: textrange = 5 // x `textrange` however,
let x = 5 // x `int` still infers x int. far, good.
overloading ... operator
now want able create textrange closed range operator ... this:
let y: textrange = 5...10 so overload ... operator in extension textranges:
extension textrange { /// given 2 text ranges, operator creates new text range incorporates /// integers within operand ranges integers between operand ranges. /// /// - parameters: /// - lowerrange: text range lower bound smaller lower bound of `upperrange`. /// - upperrange: text range lower bound greater lower bound of `lowerrange`. /// - returns: `textrange` first operand's lower bound second operand's upper bound. static func ...(lowerrange: textrange, upperrange: textrange) -> textrange { let lowerbound = lowerrange.lowerbound let upperbound = max(lowerrange.upperbound, upperrange.upperbound) assert(lowerbound <= upperbound, "cannot create textrange because lowerbound > upperbound.") return textrange(lowerbound...upperbound) } } and trouble. (what surprise: trouble begins operator overloading! 😏)
trouble
for variable of textrange type operator works expected when omit type annotation variable still instantiated textrange:
let y = 5...10 // y `textrange` that shouldn't be because:
if no type specified variable,
the default inferred type of integer literal swift standard library type int.
(see integer literals in the swift programming language)
thus, expect
5,10inferredint, nottextrange.the overload of
...operator implemented 2 operands oftextrangetype. thus,x...yshould still use original swift implementation of...ifx,ybothints.
so why compiler "decide" should use overloaded operator default ranges between 2 integer literals , interpret x , y in pattern x...y textranges?
is there way tell compiler operator should used default in case type of 2 operands not specified?
Comments
Post a Comment