My question is that
I have a size_t data, but now I want to convert it to double or int.
If I do something like
size_t data = 99999999;
in
Static cast:
static_cast<int>(data);
If your code is prepared to deal with overflow errors, you can throw an exception if data
is too large.
size_t data = 99999999;
if ( data > INT_MAX )
{
throw std::overflow_error("data is larger than INT_MAX);
}
int convertData = static_cast<int>(data);
You can use Boost numeric_cast.
This throws an exception if the source value is out of range of the destination type, but it doesn't detect loss of precision when converting to double
.
Whatever function you use, though, you should decide what you want to happen in the case where the value in the size_t
is greater than INT_MAX
. If you want to detect it use numeric_cast
or write your own code to check. If you somehow know that it cannot possibly happen then you could use static_cast
to suppress the warning without the cost of a runtime check, but in most cases the cost doesn't matter anyway.
A cast, as Blaz Bratanic suggested:
size_t data = 99999999;
int convertdata = static_cast<int>(data);
is likely to silence the warning (though in principle a compiler can warn about anything it likes, even if there's a cast).
But it doesn't solve the problem that the warning was telling you about, namely that a conversion from size_t
to int
really could overflow.
If at all possible, design your program so you don't need to convert a size_t
value to int
. Just store it in a size_t
variable (as you've already done) and use that.
Converting to double
will not cause an overflow, but it could result in a loss of precision for a very large size_t
value. Again, it doesn't make a lot of sense to convert a size_t
to a double
; you're still better off keeping the value in a size_t
variable.
(R Sahu's answer has some suggestions if you can't avoid the cast, such as throwing an exception on overflow.)
Assuming that the program cannot be redesigned to avoid the cast (ref. Keith Thomson's answer):
To cast from size_t to int you need to ensure that the size_t does not exceed the maximum value of the int. This can be done using std::numeric_limits:
int SizeTToInt(size_t data)
{
if (data > std::numeric_limits<int>::max())
throw std::exception("Invalid cast.");
return std::static_cast<int>(data);
}
If you need to cast from size_t to double, and you need to ensure that you don't lose precision, I think you can use a narrow cast (ref. Stroustrup: The C++ Programming Language, Fourth Edition):
template<class Target, class Source>
Target NarrowCast(Source v)
{
auto r = static_cast<Target>(v);
if (static_cast<Source>(r) != v)
throw RuntimeError("Narrow cast failed.");
return r;
}
I tested using the narrow cast for size_t-to-double conversions by inspecting the limits of the maximum integers floating-point-representable integers (code uses googletest):
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() - 2 })), size_t{ IntegerRepresentableBoundary() - 2 });
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() - 1 })), size_t{ IntegerRepresentableBoundary() - 1 });
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() })), size_t{ IntegerRepresentableBoundary() });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 1 }), std::exception);
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 2 })), size_t{ IntegerRepresentableBoundary() + 2 });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 3 }), std::exception);
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 4 })), size_t{ IntegerRepresentableBoundary() + 4 });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 5 }), std::exception);
where
constexpr size_t IntegerRepresentableBoundary()
{
static_assert(std::numeric_limits<double>::radix == 2, "Method only valid for binary floating point format.");
return size_t{2} << (std::numeric_limits<double>::digits - 1);
}
That is, if N is the number of digits in the mantissa, for doubles smaller than or equal to 2^N, integers can be exactly represented. For doubles between 2^N and 2^(N+1), every other integer can be exactly represented. For doubles between 2^(N+1) and 2^(N+2) every fourth integer can be exactly represented, and so on.