从通用类型创建 NSDecimalNumber 的宏
Macro to create an NSDecimalNumber from generic type
我必须即时创建 NSDecimalNumbers,但问题是有时我正在使用 int, float, double, etc
等类型,而其他类型我正在使用 NSObject*, NSString*, etc
等类型
NSDecimalNumber 的初始化对于这些不同的类型是不同的,而且每一个都打出来是非常耗时的。
我希望制作一个宏来快速排序,这样我就可以传入任何类型,它会自动为我排序。
例如
NSDecimalNumberFrom(5);
NSDecimalNumberFrom(@(5));
NSDecimalNumberFrom(@"5");
#define NSDecimalNumberFrom(__v) ({\
NSDecimalNumber *__nsdn;\
if (strcmp(@encode(__typeof__(__v)),"i")==0 ||\
strcmp(@encode(__typeof__(__v)),"d")==0) {\
__nsdn = [[NSDecimalNumber alloc] initWithDecimal:[@(__v) decimalValue]];\
} else if (strcmp(@encode(__typeof__(__v)),"@")==0) {\
__nsdn = [[NSDecimalNumber alloc] initWithDecimal:[@([__v doubleValue]) decimalValue]];\
} else {\
NSLog(@"Unknown Type");\
raise(SIGSTOP);\
}\
__nsdn;\
})
我创建了以下可以工作的宏,它检查传递值的类型,如果是“i”或“d”(例如 int、float、double 等),它会使用一种初始化方法创建 NSDecimalNumber,但如果 typeof 是“@”(例如 NSString*、NSNumber* 等),它会使用另一种初始化方法创建它。这段代码,如果被编译,将会工作......问题是编译器禁止我使用 运行 它因为它知道其他条件中的代码对于我传入的类型是无效的(即使它永远不会被处决)。
那么我怎样才能说服编译器让我这样做呢?或者有别的办法吗?
我能够通过将传递的任何内容转换为字符串来实现这一点,将错误的类型传递给字符串的格式标识符只会导致警告而不是错误,然后我能够使用 pragma 抑制这些警告(因为无论如何它们永远不会发生,编译器不够聪明,无法知道这一点)。
中提琴,
宏:
#define NSDecimalNumberFrom(__v) ({\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Weverything\"")\
NSString *__vString = @"0";\
if (strcmp(@encode(__typeof__(__v)),"i")==0) {\
__vString = [[NSString alloc] initWithFormat:@"%i", __v];\
} else if (strcmp(@encode(__typeof__(__v)),"d")==0) {\
__vString = [[NSString alloc] initWithFormat:@"%f", __v];\
} else if (strcmp(@encode(__typeof__(__v)),"@")==0) {\
__vString = [[NSString alloc] initWithFormat:@"%@", __v];\
} else {\
NSLog(@"Unknown Type");\
raise(SIGSTOP);\
}\
_Pragma("clang diagnostic pop")\
[[NSDecimalNumber alloc] initWithString:__vString];\
})
正在使用:
NSDecimalNumber *a = NSDecimalNumberFrom(5);
NSDecimalNumber *b = NSDecimalNumberFrom(@(6));
NSDecimalNumber *c = NSDecimalNumberFrom(@"7");
NSLog(@"%@", a);//logs 5
NSLog(@"%@", b);//logs 6
NSLog(@"%@", c);//logs 7
好的。玩得很开心。与 @Albert Renshaw 版本的不同之处在于,如果输入是无意义的,它将 return NaN
。
#define ENTYP(__v,__typchar) (strcmp(@encode(__typeof__(__v)),__typchar)==0)
#define STRWF(FORMAT,__s) [NSString stringWithFormat:@FORMAT,__s];
#define NSDecimalNumberFrom(__v) ({\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Weverything\"")\
NSString *__S = NULL;\
if (ENTYP(__v,"i")) { __S = STRWF("%i", __v)\
} else if (ENTYP(__v,"d")) { __S = STRWF("%f", __v)\
} else if (ENTYP(__v,"@")) { __S = STRWF("%@", __v)\
} else { __S = @"0"; }\
_Pragma("clang diagnostic pop")\
[[NSDecimalNumber alloc] initWithString:__S];\
})
-(void)test {
NSDecimalNumber *i = NSDecimalNumberFrom(2);
NSDecimalNumber *d = NSDecimalNumberFrom(5.0);
NSDecimalNumber *s = NSDecimalNumberFrom(@"7");
NSDecimalNumber *n = NSDecimalNumberFrom(@(13));
NSDecimalNumber *quatsch = NSDecimalNumberFrom(@"quatsch");
NSLog(@"i=%@ d=%@ s=%@ n=%@ quatsch=%@",i,d,s,n, quatsch);
//i=2 d=5.0 s=7 n=13
}
我必须即时创建 NSDecimalNumbers,但问题是有时我正在使用 int, float, double, etc
等类型,而其他类型我正在使用 NSObject*, NSString*, etc
NSDecimalNumber 的初始化对于这些不同的类型是不同的,而且每一个都打出来是非常耗时的。
我希望制作一个宏来快速排序,这样我就可以传入任何类型,它会自动为我排序。
例如
NSDecimalNumberFrom(5);
NSDecimalNumberFrom(@(5));
NSDecimalNumberFrom(@"5");
#define NSDecimalNumberFrom(__v) ({\
NSDecimalNumber *__nsdn;\
if (strcmp(@encode(__typeof__(__v)),"i")==0 ||\
strcmp(@encode(__typeof__(__v)),"d")==0) {\
__nsdn = [[NSDecimalNumber alloc] initWithDecimal:[@(__v) decimalValue]];\
} else if (strcmp(@encode(__typeof__(__v)),"@")==0) {\
__nsdn = [[NSDecimalNumber alloc] initWithDecimal:[@([__v doubleValue]) decimalValue]];\
} else {\
NSLog(@"Unknown Type");\
raise(SIGSTOP);\
}\
__nsdn;\
})
我创建了以下可以工作的宏,它检查传递值的类型,如果是“i”或“d”(例如 int、float、double 等),它会使用一种初始化方法创建 NSDecimalNumber,但如果 typeof 是“@”(例如 NSString*、NSNumber* 等),它会使用另一种初始化方法创建它。这段代码,如果被编译,将会工作......问题是编译器禁止我使用 运行 它因为它知道其他条件中的代码对于我传入的类型是无效的(即使它永远不会被处决)。
那么我怎样才能说服编译器让我这样做呢?或者有别的办法吗?
我能够通过将传递的任何内容转换为字符串来实现这一点,将错误的类型传递给字符串的格式标识符只会导致警告而不是错误,然后我能够使用 pragma 抑制这些警告(因为无论如何它们永远不会发生,编译器不够聪明,无法知道这一点)。
中提琴,
宏:
#define NSDecimalNumberFrom(__v) ({\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Weverything\"")\
NSString *__vString = @"0";\
if (strcmp(@encode(__typeof__(__v)),"i")==0) {\
__vString = [[NSString alloc] initWithFormat:@"%i", __v];\
} else if (strcmp(@encode(__typeof__(__v)),"d")==0) {\
__vString = [[NSString alloc] initWithFormat:@"%f", __v];\
} else if (strcmp(@encode(__typeof__(__v)),"@")==0) {\
__vString = [[NSString alloc] initWithFormat:@"%@", __v];\
} else {\
NSLog(@"Unknown Type");\
raise(SIGSTOP);\
}\
_Pragma("clang diagnostic pop")\
[[NSDecimalNumber alloc] initWithString:__vString];\
})
正在使用:
NSDecimalNumber *a = NSDecimalNumberFrom(5);
NSDecimalNumber *b = NSDecimalNumberFrom(@(6));
NSDecimalNumber *c = NSDecimalNumberFrom(@"7");
NSLog(@"%@", a);//logs 5
NSLog(@"%@", b);//logs 6
NSLog(@"%@", c);//logs 7
好的。玩得很开心。与 @Albert Renshaw 版本的不同之处在于,如果输入是无意义的,它将 return NaN
。
#define ENTYP(__v,__typchar) (strcmp(@encode(__typeof__(__v)),__typchar)==0)
#define STRWF(FORMAT,__s) [NSString stringWithFormat:@FORMAT,__s];
#define NSDecimalNumberFrom(__v) ({\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Weverything\"")\
NSString *__S = NULL;\
if (ENTYP(__v,"i")) { __S = STRWF("%i", __v)\
} else if (ENTYP(__v,"d")) { __S = STRWF("%f", __v)\
} else if (ENTYP(__v,"@")) { __S = STRWF("%@", __v)\
} else { __S = @"0"; }\
_Pragma("clang diagnostic pop")\
[[NSDecimalNumber alloc] initWithString:__S];\
})
-(void)test {
NSDecimalNumber *i = NSDecimalNumberFrom(2);
NSDecimalNumber *d = NSDecimalNumberFrom(5.0);
NSDecimalNumber *s = NSDecimalNumberFrom(@"7");
NSDecimalNumber *n = NSDecimalNumberFrom(@(13));
NSDecimalNumber *quatsch = NSDecimalNumberFrom(@"quatsch");
NSLog(@"i=%@ d=%@ s=%@ n=%@ quatsch=%@",i,d,s,n, quatsch);
//i=2 d=5.0 s=7 n=13
}