To by byl ten případ s (implicitním) přetypováním (operator SquareMatrix()), nicméně ani to mi neumožní napsat v C++ něco jako (m1*m2).trace() (na rozdíl od Swiftu).
Jo, v C++ by bylo třeba něco jako "square(m1*m2).trace()". To není zas tak zlé.
BTW umí nějaký (jiný) jazyk toto?
func *(x:Vector,y:Vector) -> Tensor {...}
func *(x:Vector,y:Vector) -> Double {...}
func *(x:Vector,y:Vector) -> AST {...}
let p:Double = a*b // scalar product
let p:Tensor = a*b // tensor product
let p:AST = a*b // AST
Docela praktické, hlavně ten AST.
V C# lze dosáhnout v podstatě téhož tak, že násobení vrátí instanci MultiplicationResult a třída MultiplicationResult bude obsahovat implicitní konverzi na double a na Tensor. AST lze získat pomocí Expression - tj. násobení místo parametru typu T bude brát parametr typu Expression<T>.
Ve Scale se použije například (ve Scale bude asi hodně možností, jak dosáhnout téhož) trik analogický tomu s CanBuildFrom - tj. násobení bude mít implicitní parametr BuildResult[T] a vracet typ T. Takto definované násobení pak může kdokoliv (i cizí kód) rozšířit na libovolný návratový typ, případně předefinovat jeho chování pro určité návratové typy. S AST lze ve Scale pracovat pomocí maker.
Benchmark by asi dopadl pro C# v tomto případě špatně.
Nevidím důvod, proč by to implementace C# nemohla zoptimalizovat stejně jako Swift. Nevím, jestli to RyuJIT od MS dokáže, nicméně MSIL lze přeložit i do LLVM (Mono, SharpLang, LLILC - zatím značně nekompletní) nebo do C (C# Native).
Pokud instanci MultiplicationResult v C# použiju víckrát, tak tam moc prostoru k optimalizaci není.
Zoptimalizuje se to tak, že
MultiplicationResult se nebude vytvářet vůbec a pro každé použití implicitní konverze se data, jenž původně byla součástí
MultiplicationResult, přímo předají kódu z implicitní konverze. Taková optimalizace může být například důsledkem escape analysis.