Подтвердить что ты не робот

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

Я изучаю D и видел много таких кодов:

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

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

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

4b9b3361

Ответ 1

В D,

to!ushort(args[1])

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

to!(ushort)(args[1])

и похож на

to<ushort>(args[1])

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

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

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

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


Что касается актера:

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

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

Ответ 2

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

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

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

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

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

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

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

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

bool yes = true;
bool no = !yes; // 'no' is false

Ответ 3

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