Как устранить «разделить на 0» ошибка в коде шаблона

Я использую пару целочисленных параметров шаблона для определения отношения, так как я не могу использовать double в качестве параметра шаблона. Преобразование в двойное число защищено от деления на ноль троичным. Это работало в более ранней версии компилятора, но Visual Studio 2013 выдает ошибку:

error C2124: divide or mod by zero

Вот упрощенная версия кода:

template<int B1, int B2>
class MyClass
{
const double B = (B2 == 0) ? 0.0 : (double) B1 / (double) B2;
// ...
};

MyClass<0, 0> myobj;

я действительно хочу B чтобы быть оптимизированным из выражений, которые используют его, когда он равен нулю, поэтому мне нужно однострочное определение. Я знаю, что могу просто использовать параметры шаблона <0, 1> чтобы обойти это, но мне интересно, есть ли способ просто убедить компилятор, что мое выражение безопасно?

12

Решение

То, что мне сказали, сработало:

 const double B = (B2 == 0 ? 0.0 : (double) B1) /
(B2 == 0 ? 1.0 : (double) B2);

Это позволяет избежать оценки короткого замыкания, предотвращая деление на 0; условные выборы происходят перед делением.


Оригинальная идея / Возможно что-то вроде этого …? (Я думаю B должно быть static const или же constexpr, но я уверен, что вы можете сортировать это …)

template<int B1, int B2>
struct MyClass
{
const double B = (double) B1 / (double) B2;
};

template <int B1>
struct MyClass<B1, 0>
{
const double B = 0.0;
};

Если есть много других вещей, которые вы хотите в MyClass и не хотите дублировать или положить в базу и т. д., вы можете переместить B Расчет в вспомогательный шаблон с использованием подхода специализации выше.

15

Другие решения

Visual Studio не может выполнить тип B1, B2 в троичной операции во время компиляции, но приведение в явном виде будет работать.

template<int B1, int B2>
class MyClass
{
double d1 = (double)B1;
double d2 = (double)B2;
const double B = (B2 == 0) ? 0.0 : d1/d2;
// ...
};

MyClass<0, 0> myobj;
2

Для любопытных — вот код, с которым я наконец-то закончил. Это, вероятно, помогает увидеть это в контексте реального мира.

template<int B1, int B2, int C1, int C2>
class BicubicFilter
{
// Based on the formula published by Don Mitchell and Arun Netravali at
// http://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
public:
BicubicFilter() : m_dMultiplier(1.0) {}
double m_dMultiplier;
double k(double x) const
{
const double B = (double) B1 / ((B2 == 0) ? 1.0 : (double) B2);
const double C = (double) C1 / ((C2 == 0) ? 1.0 : (double) C2);
x = fabs(x) * m_dMultiplier;
if (x < 1.0)
return ((2.0 - 1.5*B - C) * x*x*x) + ((-3.0 + 2.0*B + C) * x*x) + (1.0 - (2.0/6.0)*B);
if (x < 2.0)
return (((-1.0/6.0)*B - C) * x*x*x) + ((B + 5.0*C) * x*x) + ((-2.0*B - 8.0*C) * x) + ((8.0/6.0)*B + 4.0*C);
return 0.0;
}
};

k Функция выполняется не менее 4 раз на пиксель для операции изменения размера изображения, поэтому эффективность является критической. Я хочу, чтобы все константы были известны во время компиляции, чтобы компилятор мог максимально упростить выражения.

Основываясь на принятом ответе, я надеялся создать Ratio Шаблонный класс, который будет просто производить соотношение двух intс как constexpr double и специализировать его по параметрам 0, 0, Visual Studio 2013 еще не реализован constexpr поэтому я не был уверен, что компилятор будет рассматривать его как константу времени компиляции. К счастью, изменение исходного троичного выражения устранило ошибку.

2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector