Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to eliminate "divide by 0" error in template code

I'm using a pair of integer template parameters to specify a ratio, since I can't use a double as a template parameter. The conversion into a double is protected against divide-by-zero with a ternary. This worked in an earlier version of the compiler, but Visual Studio 2013 gives an error:

error C2124: divide or mod by zero

Here's a simplified version of the code:

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

MyClass<0, 0> myobj;

I really want B to be optimized out of expressions that use it when it's zero, so I need the single-line definition. I know I can just use template parameters <0, 1> to get around it, but I wonder if there's a way to just convince the compiler that my expression is safe?

like image 582
Mark Ransom Avatar asked Nov 14 '14 04:11

Mark Ransom


People also ask

Does dividing by 0 cause a runtime error?

Definition. Division by zero is a logic software bug that in most cases causes a run-time error when a number is divided by zero.

What type of error will happen if a program attempts to divide a number by zero?

Any number divided by zero gives the answer “equal to infinity.” Unfortunately, no data structure in the world of programming can store an infinite amount of data. Hence, if any number is divided by zero, we get the arithmetic exception .

What is divide error in c?

The error " divide error " occurs when some division is done by 0 'zero' . Try to identify the place where such division has occurred and modify those part.


2 Answers

What I'm told worked:

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

This avoids a reliance on short circuit evaluation preventing the divide by 0; having the conditional selections happen before the division.


Original idea / Perhaps something like this...? (I think B should be static const or constexpr, but I'm sure you can sort that...)

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;
};

If there's lots of other stuff you want in MyClass and don't want to duplicate or put in a base etc., you could move the B calculation into a supporting template using the specialisation approach above.

like image 147
Tony Delroy Avatar answered Oct 21 '22 23:10

Tony Delroy


Visual Studio is not able to typecast B1, B2 in ternary operation at compile time, but explicitly casting will work.

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;
like image 42
Rupesh Yadav. Avatar answered Oct 21 '22 22:10

Rupesh Yadav.