
Hi there,
we have been repeatedly bitten by std::numeric_limits because of its default implementation, i.e., the one beginning with
template<typename _Tp> struct numeric_limits : public __numeric_limits_base { /** The minimum finite value, or for floating types with denormalization, the minimum positive normalized value. */ static _Tp min() throw() { return static_cast<_Tp>(0); } /** The maximum finite value. */ static _Tp max() throw() { return static_cast<_Tp>(0); } /** The @e machine @e epsilon: the difference between 1 and the least value greater than 1 that is representable. */ static _Tp epsilon() throw() { return static_cast<_Tp>(0); } ...
in the <limits> header file (I am looking at GCC version 4.0.2).
Is that default implementation mandated by the standard? If so, well... fine. But if it is not mandated then I think it makes much sense to remove it as it seems a perfect recipe for disaster.
Another issue is: shouldn't, e.g., std::numeric_limits<int> and std::numeric_limits<const int> be completely equivalent? Here is a little C++ program demonstrating what I mean:
#include <limits> #include <iostream>
using namespace std;
struct Foo { Foo(int) { }; operator int() { return 27; } };
int main() { std::cout << std::numeric_limits<Foo>::is_bounded << std::endl; std::cout << std::numeric_limits<Foo>::max() << std::endl;
std::cout << std::numeric_limits<const int>::is_bounded << std::endl; std::cout << std::numeric_limits<const int>::max() << std::endl;
std::cout << std::numeric_limits<int>::is_bounded << std::endl; std::cout << std::numeric_limits<int>::max() << std::endl; }
Here it prints the following:
0 27 0 0 1 2147483647
All the best,
Roberto

Hi Roberto,
Is that default implementation mandated by the standard? If so, well... fine.
I think it is: 18.2.1.1/2. But I don't know the rationale...
But if it is not mandated then I think it makes much sense to remove it as it seems a perfect recipe for disaster.
Another issue is: shouldn't, e.g., std::numeric_limits<int> and std::numeric_limits<const int> be completely equivalent?
I tend to agree, but I'm not sure would be conforming: see 18.2.1/2 and /4, in particular, which says: "Non fundamental standard types, such as complex<T>, shall not have specializations".
I don't think a cv-qualified fundamental type qualifies as a fundamental type. According to 3.9.3, "A type mentioned in 3.9.1 and 3.9.2 is a cv-unqualified type", where 3.9.1 is the section named "Fundamental types" and describing all those types.
Paolo.

Paolo Carlini wrote:
Is that default implementation mandated by the standard? If so, well... fine.
I think it is: 18.2.1.1/2. But I don't know the rationale...
But if it is not mandated then I think it makes much sense to remove it as it seems a perfect recipe for disaster.
Another issue is: shouldn't, e.g., std::numeric_limits<int> and std::numeric_limits<const int> be completely equivalent?
I tend to agree, but I'm not sure would be conforming: see 18.2.1/2 and /4, in particular, which says: "Non fundamental standard types, such as complex<T>, shall not have specializations".
I don't think a cv-qualified fundamental type qualifies as a fundamental type. According to 3.9.3, "A type mentioned in 3.9.1 and 3.9.2 is a cv-unqualified type", where 3.9.1 is the section named "Fundamental types" and describing all those types.
Dear Paolo,
I think your reading of the standard is completely correct. It seems that, in order to play safe, one really has to use the is_specialized member. Many thanks,
Roberto
participants (2)
-
Paolo Carlini
-
Roberto Bagnara