Is visual C ++ std :: isfinite () standard?

I have a wrapper class that has a simple and lightweight weighted implicit conversion operator equal to double

.

I like to use it as I would use double, for example:

if (!std::isfinite(myVar)) ...

      

But the visual C ++ implementation std::isfinite(double)

is actually a template that gets its argument by copying.

So my wrapper class instance constructor gets called and it is not weighted by weight.

To avoid this, I have to write:

if (!std::isfinite((double)myVar)) ...

      

for each call: (

If visual C ++ std::isfinite()

was defined as it is on cppreference.com , I wouldn't have to throw every call: ([edit] I might be wrong, Integral is not an actual type ... but ... [edit] It is still shouldn't accept custom types?)

bool isfinite( float arg );
bool isfinite( double arg );
bool isfinite( long double arg );
bool isfinite( Integral arg );

      

I'm not sure what the standard says about this. Is the vC ++ template std::isfinite

standard?

Should I report this as a bug on Microsoft connect?

Should I define my own isfinite(double)

which is calling std::isfinite

?

change

Or maybe this is not a problem, as in the release, the calls become inlined and no copy occurs? (ok i will try to test it right now and update in a few minutes)

change 2

It doesn't seem to be inserted into the release build with / Ob 2 (built-in any suitable function)

edit 3

on request, sample:

struct DoubleWrapper {

  double value;

  DoubleWrapper(double value) : value(value) {
    printf("copy Ctor\n");
  }

  DoubleWrapper(const DoubleWrapper & that) : value(that.value) {}

  operator double() const {
    return this->value;
  }
};

int main() {

  DoubleWrapper a(rand());      //rand to prevent optimization

  auto res = std::isfinite(a);

  printf("%d", res);            //printf to prevent optimization
}

      

change 4

So, based on Ben Voigt's comment, this is what I added to my class header:

#include <cmath>

namespace std {
    inline bool isfinite(const DoubleWrapper<double> & dw) {
        return isfinite((double)dw);
    }
}

      

Is this the right decision?

The only thing is, should I do the same for all <cmath>

functions that take double?

change 5

I am replying to Shafik Yagmur's answer because the comment is too limited (maybe I should start a new question)

If I understood correctly, instead of my edit 4, I should add this to the class header:

inline bool isfinite(const DoubleWrapper<double> & dw) {
    return isfinite((double)dw);
}

using std::isfinite;

      

Do you need to place it in the namespace or keep it in the "global" namespace?

But that means I have to change all my calls from std::isfinite(dw)

to isfinite(dw)

.

Ok, but I understand that there are many things that I do not understand. I am embarrassed.

I understand that adding an overload to std is not valid.

However, adding template specialization is allowed? What for? Who cares?

Anyway, I tried it and this is not a solution to my problem, because this specialization:

template<> inline __nothrow bool std::isfinite(const MagicTarget<double> & mt) {
    return std::isfinite((double)mt);
}

      

will not be selected by the compiler over the standard one:

template<class _Ty> inline __nothrow bool isfinite(_Ty _X)
{
    return (fpclassify(_X) <= 0);
}

      

To be chosen it must be

template<> inline __nothrow bool std::isfinite(MagicTarget<double> mt) {
    return std::isfinite((double)mt);
}

      

But this will still call a copy of the Ctor :(

Surprisingly, the overload (see change 4) is chosen over the standard template ... I'm starting to think that some of the C ++ rules are too subtle for me :(

But first, why are there cmath functions and especially the std::isfinite

template?

What's the point in accepting anything else that is floating point types?

In any case, vC ++ std::isfinite

calls std::fpclassify

, which is only defined for float, double and long double. So ... What's the point?

I think the standard fee is screwed in by allowing cmath functions to be templates. They should only be defined for types that are relevant, or can accept their arguments as universal references.

To do this, sorry for writing ...

I'll go for (not to std) overload. Thank!

+3


source to share


1 answer


Addressing edit 4 to your question, since with the help of the comments you get closer to the final solution.

You cannot add it to the namespace std

, you must add it to your own namespace and rely on argument-dependent lookup see Is it good practice to overload math functions in std namespace in C ++ for more details.

Given the committee's standard explicit desire to restrict functions cmath

to be called only with arithmetic types, relying on implicit conversion is not a good idea. So doing an explicit conversion with a cast is a safe way for all functions cmath

:



isfinite((double)dw)

      

For details on this, see Is it valid to pass non-arithmetic types as arguments to cmath functions? ...

+3


source







All Articles