我的代码的简化版本,显示了问题:
protocol Transformer {
typealias Input
typealias Output
func transform(s: Input) -> Output
}
protocol InputType {}
protocol OutputType {}
extension Int: OutputType {}
extension String: InputType {}
struct StringToInt: Transformer {
typealias Input = String
typealias Output = Int
func transform(s: Input) -> Output {
return s.characters.count
}
}
typealias Transform = InputType -> OutputType
func convert<T: Transformer where T.Input == InputType, T.Output == OutputType>
(transformer: T) -> Transform {
return transformer.transform
}
convert(StringToInt()) // error: Cannot invoke 'convert' with an argument list of type '(StringToInt)'
我猜错了,因为编译器无法访问StringToInt
并验证Input
和Output
确实符合InputType
和OutputType
分别
对我来说,解决这个问题的最佳方法是直接在协议中约束相关类型。它会更具表现力,编译器会有更多信息。但只是做typealias Input: InputType
不起作用。
有没有办法约束相关类型?
答案 0 :(得分:1)
您可以为Transformer
协议
extension Transformer where Input: InputType, Output: OutputType {
func convert() -> Input -> Output {
return transform
}
}
现在,您可以在convert
实例上调用StringToInt
方法。
StringToInt().convert()
但对于其他没有Input
和Output
采用InputType
和OutputType
的类型,它不会编译
struct DoubleToFloat: Transformer {
func transform(s: Double) -> Float {
return Float(s)
}
}
DoubleToFloat().convert() // compiler error
答案 1 :(得分:0)
删除#include "tttfs.h"
uint8_t little[4];
int tttfs_create(int size, char *name);
void inttolitend(uint32_t x, uint8_t* lit_int);
int main(){
tttfs_create(7, "disk.tfs");
}
int tttfs_create(int size, char *name){
FILE *f = NULL;
if ((f = fopen(name, "wb"))!=NULL)
{
disk *d = malloc(sizeof(disk));
d->diskBlock = malloc(1024);
d->id = 1;
int i;
for(i = 0; i<size; i++){
printf("%d\n", i);
d->diskBlock[i].unBlock = malloc(1024); //I got the segmentation fault here
}
inttolitend(size, little);
for(i = 0; i<4; i++){
d->diskBlock[0].unBlock[i] = little[i];
}
for(i = 0; i<size; i++){
fwrite(&d->diskBlock[i],1024,1,f);
}
}
else
printf("Erreur\n\n");
return 0;
}
void inttolitend(uint32_t x, uint8_t* lit_int){
lit_int[3] = (uint8_t)x / (256*256*256);
lit_int[2] = (uint8_t)(x % (256*256*256)) / (256*256);
lit_int[1] = (uint8_t)((x % (256*256*256)) % (256*256)) / 256;
lit_int[0] = (uint8_t)((x % (256*256*256)) % (256*256)) % 256;
}
别名用法,为输入和输出类型添加泛型,并将其映射到Transform
,然后您将获得Transformer
的工作代码以及你写的其他变形金刚:
StringToInt
顺便说一下,你不需要为func convert<T: Transformer, I, O where T.Input == I, T.Output == O>
(transformer: T) -> I -> O {
return transformer.transform
}
convert(StringToInt())
指定类型别名,如果你指定了实际的类型,编译器就可以从函数定义中推断出那些:
StringToInt