From: Marc on
Hello,

I notice that the default numeric_limits in C++0X reads:
static constexpr T min() throw() { return T(); }

I assume this fails if T doesn't have a constexpr default constructor
(T isn't a literal type).

It's never been clear whether users were supposed to provide a
specialization of numeric_limits for their own number types, but this
sounds like one has to be careful using numeric_limits.

If I write something like:
if(numeric_limits<T>::is_bounded) {
... use numeric_limits<T>::min() ...
}
do I have the guarantee that the compiler won't try to instantiate min
for wrong types? (I could test std::is_builtin<T>::value (can't
remember the real name) but the issue is the same) Or do I need to
write 2 functions?

Since there is no has_epsilon, for a type that has
numeric_limits<T>::is_specialized, I would check epsilon()==T() which
is a bad idea. Should I assume that only float, double and long double
have epsilon?

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Bo Persson on
Marc wrote:
> Hello,
>
> I notice that the default numeric_limits in C++0X reads:
> static constexpr T min() throw() { return T(); }
>
> I assume this fails if T doesn't have a constexpr default
> constructor (T isn't a literal type).

If fails as a constant expression, but is still legal in places where
a constant isn't requiered (assuming T() is valid, but not constexpr).

>
> It's never been clear whether users were supposed to provide a
> specialization of numeric_limits for their own number types, but
> this sounds like one has to be careful using numeric_limits.

If the class is to behave as a numeric type, it would probably need a
specialization. The default numeric_limits class only provides dummy
values for most of its members.

>
> If I write something like:
> if(numeric_limits<T>::is_bounded) {
> ... use numeric_limits<T>::min() ...
> }
> do I have the guarantee that the compiler won't try to instantiate
> min for wrong types? (I could test std::is_builtin<T>::value (can't
> remember the real name) but the issue is the same) Or do I need to
> write 2 functions?

The compiler will have to compile all parts of the if-statement, even
those that are statically known never to execute. If you want to avoid
this, you will probably have to use some meta programming, like using
C++0x std::enable_if.

>
> Since there is no has_epsilon, for a type that has
> numeric_limits<T>::is_specialized, I would check epsilon()==T()
> which is a bad idea. Should I assume that only float, double and
> long double have epsilon?

Or any other type with a user specialized numeric_limits.



Bo Persson



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 24 May, 16:46, Marc <marc.gli...(a)gmail.com> wrote:
> Hello,
>
> I notice that the default numeric_limits in C++0X reads:
> static constexpr T min() throw() { return T(); }
>
> I assume this fails if T doesn't have a constexpr default constructor
> (T isn't a literal type).
>
> It's never been clear whether users were supposed to provide a
> specialization of numeric_limits for their own number types, but this
> sounds like one has to be careful using numeric_limits.
>
> If I write something like:
> if(numeric_limits<T>::is_bounded) {
> ... use numeric_limits<T>::min() ...}
>
> do I have the guarantee that the compiler won't try to instantiate min
> for wrong types? (I could test std::is_builtin<T>::value (can't
> remember the real name) but the issue is the same) Or do I need to
> write 2 functions?

>From the latest draft:

For all members declared static constexpr in the numeric_limits
template, specializations shall define
these values in such a way that they are usable as constant
expressions.

and

Meaningful for all specializations in which is_bounded != false, or
is_bounded == false && is_-
signed == false.

Note that it says "Meaningful" not "Defined". All the members need to
be defined for all specialized types - but they aren't meaningful
except under the circumstances stated in the standard.

> Since there is no has_epsilon, for a type that has
> numeric_limits<T>::is_specialized, I would check epsilon()==T() which
> is a bad idea. Should I assume that only float, double and long double
> have epsilon?

For the built in types !is_integer will do as a check (and is given as
an example for epsilon in 8.3.1.5) but it's not clear that that is
good enough in general and if it is believed to be so then why not say
"Meaningful if !is_integer" rather than "Meaningful for floating point
types".

Consider a ratio of two unbounded integers - There would be no
epsilon. Fortunately the sort of people who care about this are
unlikely to be using such types.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Marc on
(thank you and Bo Persson for your answers)

On May 25, 8:55 pm, Nick Hounsome <nick.houns...(a)googlemail.com>
wrote:
> From the latest draft:
>
> For all members declared static constexpr in the numeric_limits
> template, specializations shall define
> these values in such a way that they are usable as constant
> expressions.

I had a small doubt whether this referred only to the standard
specializations or also the user-provided ones, but ok.

Does "member" only refer to variables like digits? Or does it also
refer to functions like min(), in which case it implies a user is
forbidden from specializing numeric_limits for a non-literal type (or
at least any type for which a compile-time constant is meaningless)?

> Meaningful for all specializations in which is_bounded != false, or
> is_bounded == false && is_-
> signed == false.
>
> Note that it says "Meaningful" not "Defined". All the members need to
> be defined for all specialized types - but they aren't meaningful
> except under the circumstances stated in the standard.

But they still need to be "usable as constant expressions", even if
the value is meaningless.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 27 May, 09:35, Marc <marc.gli...(a)gmail.com> wrote:
> (thank you and Bo Persson for your answers)
>
> On May 25, 8:55 pm, Nick Hounsome <nick.houns...(a)googlemail.com>
> wrote:
>
> > From the latest draft:
>
> > For all members declared static constexpr in the numeric_limits
> > template, specializations shall define
> > these values in such a way that they are usable as constant
> > expressions.
>
> I had a small doubt whether this referred only to the standard
> specializations or also the user-provided ones, but ok.
>
> Does "member" only refer to variables like digits? Or does it also
> refer to functions like min(), in which case it implies a user is
> forbidden from specializing numeric_limits for a non-literal type (or
> at least any type for which a compile-time constant is meaningless)?

What do you mean by a non-literal type?
A user isn't forbidden from specializing - a user MUST specialize ALL
the members for any type for which is_specialized is true

> > Meaningful for all specializations in which is_bounded != false, or
> > is_bounded == false && is_-
> > signed == false.
>
> > Note that it says "Meaningful" not "Defined". All the members need to
> > be defined for all specialized types - but they aren't meaningful
> > except under the circumstances stated in the standard.
>
> But they still need to be "usable as constant expressions", even if
> the value is meaningless.

Yes but that's not a problem they can just return any constant value
if they are not meaningful.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]