методы с переменным числом аргументов: проверка, является ли аргумент блоком с определением типа - PullRequest
3 голосов
/ 24 октября 2011

Я создал метод veriadic Category в NSArray, чтобы отфильтровать его в словарь с заданными блоками и ключами

typedef BOOL (^TestBlock)(id element);
- (NSDictionary *)dictionaryByFilteringWithBlocksAndKeys:(TestBlock)firstBlock, id firstKey,... NS_REQUIRES_NIL_TERMINATION;

Использование:

NSArray *array = [NSArray arrayWithObjects:@"a", @"aa", @"ab", @"cc", @"cd", @"dd", nil];
NSDictionary *dict = [array dictionaryByFilteringWithBlocksAndKeys:
                                    ^BOOL(id element) {return [element hasPrefix:@"a"];},@"a",
                                    ^BOOL(id element) {return [element hasPrefix:@"c"];},@"c", 
         nil];

Это работает довольно хорошо, но мне интересно, как я могу проверить, имеет ли данный блок (кроме первого) сигнатуру typedef.

Я получаю блоки от va_list с TestBlock block = va_arg(args, TestBlock);, но он также ест блоки без смысла, такие как

NSDictionary *dict = [array dictionaryByFilteringWithBlocksAndKeys:
                                    ^BOOL(id element) {return [element hasPrefix:@"a"];}, @"a", 
                                    ^(id element) {;}, @"c", 
                          nil];

без жалоб.

Есть ли способ проверить, имеет ли блок ту же сигнатуру, что и typedef во время выполнения?

1 Ответ

4 голосов
/ 24 октября 2011

Нет, проверить невозможно. Это потребует нового синтаксиса в компиляторе. По сути, вы хотите, чтобы «эти аргументы были необязательными / переменными, но должны следовать шаблону этого типа».

Также обратите внимание на то, что трактовка определенного типизированного списка аргументов как va_list также технически некорректна. Это будет работать по совпадению на большинстве ABI, но не на всех. (Не то, чтобы вы это делали, но это часто встречается в этих контекстах).

Можете ли вы дать мне пример того, что вы имеете в виду под специально напечатанным список аргументов?

Конечно, рассмотрим:

id objc_msgSend(id,SEL,...);

Это список аргументов var-args. Теперь вы можете подумать, что можете сделать это:

objc_msgSend(mutableArray, @selector(addObject:), anObject);

Но технически вы не можете. varargs не совместимы со специально типизированными списками аргументов, согласно спецификации C. Таким образом, вам нужно набрать:

void (*func)(id,SEL,id) = (void*)objc_msgSend;
func(mutableArray, @selector(addObject:), anObject);

То есть, если вызываемый API имеет значение , а не также varargs, то сайт вызова должен быть скомпилирован с объявлением вызова с полной информацией о типе аргумента ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...