C++ Logo

std-proposals

Advanced search

Re: Make non-specialized numeric_limits<T> use ill-formed

From: Thomas Mercier <thomas.mercier.jr_at_[hidden]>
Date: Sat, 11 Apr 2020 14:15:22 -0700
That makes sense.

I googled around for "is_specialized" to see how people are using it. Most
of the examples I found had static_asserts or references to undefined
templates checking if there is a specialization for the provided type...
exactly the sort of thing I was hoping for.

https://chromium.googlesource.com/external/webrtc/+/35c5336e602c14925cb272bf7c94e569bd100789/webrtc/base/numerics/safe_conversions.h#41
https://gitlab.com/gitlab-org/security-products/demos/protobuf/blob/6bbe197e9c1b6fc38cbdc45e3bf83fa7ced792a3/python/google/protobuf/pyext/safe_numerics.h

https://vtk.org/doc/release/7.1/html/vtkAtomicTypeConcepts_8h_source.html

I did find cases that would break. Here's one:
https://git.new-vision.com/library/boost-header-only/blob/8f405f18f0ac2d2b1a25e7a48a4f50d05a410a14/include/boost/math/tools/config.hpp#L312


If the language is changed to say is_specialized is the only defined member
in the default template, rather than all use is completely ill-formed then
this could be refactored to something like:

static const bool value = boost::is_integral<T>::value
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
      || []{
          if constexpr(std::numeric_limits<T>::is_specialized)
            return std::numeric_limits <T>::is_integer;
          else
            return false;
        }()
#endif
      ;

or

template <class T>
struct is_specialized_integer
{
    static constexpr bool get() {
        if constexpr(std::numeric_limits<T>::is_specialized)
            return std::numeric_limits<T>::is_integer;
        else
            return false;
    }
};

static const bool value = boost::is_integral<T>::value
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
      || is_specialized_integer<T>::get()
#endif
      ;

Leaving only those who actually depend on the 0 or false default values
subject to breaking. Not sure if that helps enough.

On Fri, Apr 10, 2020 at 11:43 PM Bo Persson via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On 2020-04-10 at 20:27, Thomas Mercier via Std-Proposals wrote:
> > Hi,
> >
> > I encountered some surprising behavior from the std::numeric_limits<T>
> > class template when experimenting with std::byte. The integer
> > representation of the maximum std::byte value is 0 according to
> > std::numeric_limits<std::byte>::max(). That is because there is no
> > specialization of std::numeric_limits<T> for std::byte, because
> > std::byte is not an arithmetic type. Ok, fine. But the fact that the
> > program compiles, and produces an unexpected value is worrisome!
> >
> > The standard specifies that "The default numeric_­limits<T> template
> > shall have all members, but with 0 or false values."
> > (https://eel.is/c++draft/numeric.limits#3)
> >
> > I would prefer to see this say something like, "a program which uses the
> > default numeric_limits<T> template is ill-formed", so that an error is
> > produced at compile time rather than a value initialized result
> > (
> https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/limits#L321 and
>
> >
> https://github.com/llvm/llvm-project/blob/master/libcxx/include/limits#L150
> ).
> >
> > Does anyone know why the current wording specifies "0 or false values",
> > or what any objections to my suggested change might be?
> >
> > https://godbolt.org/z/YVSECn
> >
> > Thanks,
> > T.J.
> >
>
> I believe the current wording is to support code like this
>
> if (numeric_limits<T>::is_specialized)
> // use other members
> else
> // alternate code
>
>
> Before the invention of constexpr-if both paths of the if-statement just
> had to contain valid code to compile. Thus valid dummy values (0/false)
> for non-numeric T's.
>
>
> Bo Persson
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2020-04-11 16:18:30