Восклицательный оператор? - PullRequest
       2

Восклицательный оператор?

23 голосов
/ 24 декабря 2011

Я изучаю D и видел много кода, подобного этому:

ushort x = to!ushort(args[1]);

Я предполагаю, что это приводит от args[1] к ushort, но в чем разница между этим и cast(ushort)?

РЕДАКТИРОВАТЬ: И что еще используется оператор восклицательного знака?

Ответы [ 3 ]

33 голосов
/ 24 декабря 2011

In D,

to!ushort(args[1])

является сокращением для экземпляра шаблона

to!(ushort)(args[1])

и аналогично

to<ushort>(args[1])

в таких языках, как C ++ / Java / C #.

Восклицательный знак должен отметить тот факт, что это не обычный аргумент, а аргумент шаблона.

В нотации не используются угловые скобки, потому что нелепо трудно правильно проанализировать для компилятора (они делают грамматику очень контекстно-зависимой), что делает ее намного более сложной сложно реализовать правильный компилятор. См. здесь для получения дополнительной информации.

Единственное другое использование, о котором я знаю, - это просто унарная операция «не» (например, false == !true) ... В данный момент я не могу думать ни о каком другом использовании.


Относительно актерского состава:

cast(ushort) является неконтролируемым приведением, поэтому оно не будет генерировать исключение, если значение выходит за пределы диапазона.

to!ushort() является проверенным приведением, поэтому оно выдает исключение, если значение выходит за пределы диапазона.

3 голосов
/ 24 декабря 2011

Восклицательный знак здесь не является оператором, это всего лишь маркерная часть явного синтаксиса создания экземпляра шаблона (подробно описано здесь ).

std.conv.to (docs ) - это шаблон функции для преобразования между произвольными типами.Он полностью реализован в библиотеке и не имеет специальной поддержки в языке.Он имеет более широкую область действия по сравнению с оператором приведения.

Шаблон to принимает два параметра типа;тип "to" и тип "from" в указанном порядке.В вашем примере шаблон явно создается с аргументом одного типа ushort для параметра "to", а аргумент второго типа string (при условии, что args происходит от первого параметра до main), автоматически выводитсяиз аргумента обычной функции, переданного функции (args[1]) в качестве параметра from.

Результирующая функция принимает строковый параметр и возвращает разбор ushort из этой строки или выдает исключение, если она не удалась,Оператор приведения не будет пытаться выполнить такое высокоуровневое преобразование.

Обратите внимание, что если имеется более одного явного параметра шаблона или этот параметр содержит более одного токена (ushort - это одно ключевое словоtoken), вы должны заключить список параметров шаблона в круглые скобки:

ushort result;
result = to!(typeof(result))(args[1]);

В этом примере typeof, (, result и ) - это четыре отдельных токена, поэтому круглые скобкитребуется.

Чтобы ответить на ваш последний вопрос, токен ! также используется для унарного оператора not, не связанного с экземплярами шаблона:

bool yes = true;
bool no = !yes; // 'no' is false
2 голосов
/ 25 декабря 2011

У вас уже есть два превосходных ответа от jA_cOp и Merhdad.Я просто хочу ответить прямо на вопрос OP ( в чем разница между этим и приведением (ushort)? ) - Разница в том, что cast(ushort)args[1] не будет работать (вы не можете просто преобразовать строку в строкутак), в то время как шаблон to!(type)(param) знает, что делать со строкой и как преобразовать ее в примитивный тип.

...