https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87982

Jan van Dijk <j.v.dijk at tue dot nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |j.v.dijk at tue dot nl

--- Comment #3 from Jan van Dijk <j.v.dijk at tue dot nl> ---
Isn't the real problem that the standard does not specify any requirements
about the type of the count argument (or a precondition on its value)? 

Should that be a built-in integral type? Then the issue is solved by doing a
static_assert<is_integral_v<_Size>> to the implementation.

One could also argue that the counter merely be convertible to a std::size_t,
and the question (to WG21) is why then the count type is a template argument in
the first place. (One could also argue that it should be a std::ptrdiff_t,
since the algorithm really operates on a range [ptr,ptr+count] --- that would
also allow an assert(count>=0) in the implementation.)

If the intention is really that also user-defined types are supported, the
requirements on such types should be spelled out (by WG21). As an example, the
code below uses a custom counter object that can can be converted to (=> and
compared with) an integer value. Reasonable enough. However, it does not
compile because of what really seems to be an undocumented implementation
detail in stl_algo.h: the usage of decltype(__n + 0) to compute a counter type
for internal usage. Is the code below valid or not?

It is remarkable how much Sunday morning can be spent on such an innocuous
issue :-)

cat 87892_2.cpp
#include <algorithm>

struct counter
{
        counter(unsigned n);
        operator unsigned() const;
        counter& operator--();
private:
        template <class T> counter operator+(T v) const;
};

void foo()
{
  int a[2];
  std::generate_n(a, counter(2), []{ return 0;});
}

g++ -c 87892_2.cpp
In file included from /home/jan/local/gcc-head/include/c++/9.0.1/algorithm:62,
                 from 87892_2.cpp:1:
/home/jan/local/gcc-head/include/c++/9.0.1/bits/stl_algo.h: In instantiation of
‘_OIter std::generate_n(_OIter, _Size, _Generator) [with _OIter = int*; _Size =
counter; _Generator = foo()::<lambda()>]’:
87892_2.cpp:15:48:   required from here
/home/jan/local/gcc-head/include/c++/9.0.1/bits/stl_algo.h:4448:27: error:
‘counter counter::operator+(T) const [with T = int]’ is private within this
context
 4448 |       for (__decltype(__n + 0) __niter = __n;
      |                       ~~~~^~~
87892_2.cpp:9:29: note: declared private here
    9 |  template <class T> counter operator+(T v) const;
      |

Reply via email to