Иногда возникает необходимость проверить является ли некоторый тип числовым, при этом, если тип относится к числовым, то не важно целое ли это число или же с плавающей точкой.
То есть решение должно быть универсальным…
Осуществить эту проверку можно с использованием следующего шаблона:
import std.meta : allSatisfy; import std.range : zip; import std.traits : isIntegral, isFloatingPoint, Unqual; template allArithmetic(T...) if (T.length >= 1) { template isNumberType(T) { enum bool isNumberType = isIntegral!(Unqual!T) || isFloatingPoint!(Unqual!T); } enum bool allArithmetic = allSatisfy!(isNumberType, T); }
Работает это так: сначала убеждаемся в том, что набор типов (или кортеж типов), имеет длину большую или равную единице (если это так, компиляция программы пройдет успешно, в ином случае, dmd выведет ошибку о несоответствии сигнатуры функции и шаблона), а затем определяем вспомогательный шаблон isNumberType.
Шаблон isNumberType принимает некоторый тип T, снимает с него квалификатор (если он есть), то есть убирает const, immutable и подобные из определения типа. Избавление от квалификатора достигается с помощью шаблона Unqual из стандартной библиотеки. После того, как тип очищен от лишней информации, с помощью двух шаблонов проверяем его принадлежность к одному из двух разных множеств числовых типов — к множеству целых числовых типов и к множеству типов с плавающей точкой. Эта проверка реализуется с помощью шаблонов из стандартной библиотеки: isIntegral и isFloatingPoint соответственно.
Таким образом, получается, что шаблон isNumberType проверяет принадлежность типа к числовым. В принципе, достаточно одного этого шаблона, но хотелось бы иметь более универсальное решение, распространенное на любое произвольное количество типов, эту задачу решает шаблон allArithmetic.
Шаблон allArithmetic принимает произвольный набор типов T и проверяет принадлежность всех элементов кортежа типов к арифметическим (числовым). Если хотя бы один из элементов кортежа типов не окажется числовым, то компилятор выдаст ошибку о несоответствии сигнатуры. Проверка всех элементов набора типов производится с помощью шаблона allSatisfy, который принимает некоторый шаблон и набор типов, проверяет, все ли элементы набора удовлетворяют принятому шаблону.
Шаблон allSatisfy также входит в стандартную библиотеку D.
Созданный нами шаблон allArithmetic принимает набор типов (длина этого набора должна быть больше или равна единице) и может использоваться в самых разных функциях как ограничение сигнатуры (signature contraint).