Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Мне кажется, что для функций с тремя-четырьмя параметрами это будет неимоверно громоздко. Например, у меня есть функция MulAddDiv, вычисляющая выражение "(a * b + c) / d" с использованием особенностей x86 (команды перемножения 32-разрядных в 64-разрядное, и обратный вариант деления). Соответственно, для 32-разрядных типов используется эта реализация, а все остальные варианты, имеющие хотя бы один 64-разрядный параметр, реализуются "втупую".
Если аргументов несколько, то опция по сути только одна
template<typename T1, typename T2 , typename T3> Res f(T1 a, T2 b, T3 c);
т.е. иметь столько параметров шаблона, сколько и аргументов.
Предложенный селектор можно специализировать для аргументов-целых чисел, разрядностью меньше чем 32 и чисел разрядностью больше 32. Но это будет больше писанины и использования стандартной библиотеки (потребуется is_integral из type_traits и всякое из <limits>)
Для двух входных аргументов как-то так
template<typename T1, typename T2, typename Enabler = void> struct ResultTypeSelector {typedef T type;};
template<typename T1, typename T2>
struct ResultTypeSelector <T, typename std::enable_if_t<
(std::is_intergal<T1>::value) && (std::is_intergal<T2>::value) &&
(std::numeric_limits<T1>::digits <= 32) &&
(std::numeric_limits<T2>::digits <= 32)
>
{
//тут описываешь свои правила
typedef int32_t ResType; //тип результата
typedef int32_t IntermedType; //тип промежуточных данных
};
template<typename T1, typename T2>
struct ResultTypeSelector <T, typename std::enable_if_t<
(std::is_intergal<T1>::value) && (std::is_intergal<T2>::value) &&
((std::numeric_limits<T1>::digits > 32) ||
(std::numeric_limits<T2>::digits > 32))
>
{
//тут описываешь свои правила
typedef int64_t ResType; //тип результата
typedef int64_t IntermedType; //тип промежуточных данных
};
Перед вычислениями внутри функции все аргументы приводишь к IntermedType.