Проверка любого типа на принадлежность к числовым

Иногда возникает необходимость проверить является ли некоторый тип числовым, при этом, если тип относится к числовым, то не важно целое ли это число или же с плавающей точкой. То есть решение должно быть универсальным.

Осуществить проверку можно с использованием следующего шаблона:

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).

Добавить комментарий