Date: Thu, 29 Aug 2019 10:39:21 -0400
On Thu, Aug 29, 2019 at 9:51 AM Matthew Woehlke via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On 28/08/2019 08.23, Andrew Tomazos via Std-Proposals wrote:
> > See:
> >
> >
> https://docs.google.com/document/d/1gBdBualdIU1bpgW_El4GT-p0he9Yr7D52xmLmHes5Qo/edit?usp=sharing
>
> TBH, I like the name "indices" much better than "upto". It seems a shame
> to lose that to a special variant which always casts, which is not
> always the right thing. Especially as in many cases you could as easily
> write:
>
> for (auto const i : std::indices(static_cast<size_t>(...)))
>
> ...and have the same effect with less change for user confusion. (Also,
> size_t can easily be replaced with ssize_t in the above.)
>
> I wonder if instead we could make this work?
>
> int x = ...;
> for (auto const i : std::indices(x)) // i → int
> ;
> for (auto const i : std::indices<size_t>(x)) // i → size_t
> ;
>
> I'm not sure, though, how to make deduction work so that, with no
> arguments, you get back the same type as the input, but *with*
> arguments, you accept anything and static_cast to the template type.
>
Easy ways to do that would be:
template<class T> T indices(T max); // indices<int>(UINT_MAX) begins by
implicitly converting UINT_MAX to int
or:
template<class R, class T> R indices_impl(T max); //
indices_impl<int>(UINT_MAX) never converts UINT_MAX to int
template<class R = void, class T>
auto indices(T max) {
if constexpr (std::is_void_v<R>) {
return indices_impl<T>(max);
} else {
return indices_impl<R>(max);
}
}
Incidentally, there has been some discussion yesterday in the #ranges Slack
channel about the fact that
- std::iota(0, 10) compiles fine, producing a sized range
- std::iota(0, 10u) does not compile
- std::iota(0, 10.0f) compiles fine, producing an unsized range
- std::iota(short(0), 65536) compiles fine, producing an unsized and
infinite range
In short: implicit conversions are the devil and should be avoided in good
APIs.
–Arthur
std-proposals_at_[hidden]> wrote:
> On 28/08/2019 08.23, Andrew Tomazos via Std-Proposals wrote:
> > See:
> >
> >
> https://docs.google.com/document/d/1gBdBualdIU1bpgW_El4GT-p0he9Yr7D52xmLmHes5Qo/edit?usp=sharing
>
> TBH, I like the name "indices" much better than "upto". It seems a shame
> to lose that to a special variant which always casts, which is not
> always the right thing. Especially as in many cases you could as easily
> write:
>
> for (auto const i : std::indices(static_cast<size_t>(...)))
>
> ...and have the same effect with less change for user confusion. (Also,
> size_t can easily be replaced with ssize_t in the above.)
>
> I wonder if instead we could make this work?
>
> int x = ...;
> for (auto const i : std::indices(x)) // i → int
> ;
> for (auto const i : std::indices<size_t>(x)) // i → size_t
> ;
>
> I'm not sure, though, how to make deduction work so that, with no
> arguments, you get back the same type as the input, but *with*
> arguments, you accept anything and static_cast to the template type.
>
Easy ways to do that would be:
template<class T> T indices(T max); // indices<int>(UINT_MAX) begins by
implicitly converting UINT_MAX to int
or:
template<class R, class T> R indices_impl(T max); //
indices_impl<int>(UINT_MAX) never converts UINT_MAX to int
template<class R = void, class T>
auto indices(T max) {
if constexpr (std::is_void_v<R>) {
return indices_impl<T>(max);
} else {
return indices_impl<R>(max);
}
}
Incidentally, there has been some discussion yesterday in the #ranges Slack
channel about the fact that
- std::iota(0, 10) compiles fine, producing a sized range
- std::iota(0, 10u) does not compile
- std::iota(0, 10.0f) compiles fine, producing an unsized range
- std::iota(short(0), 65536) compiles fine, producing an unsized and
infinite range
In short: implicit conversions are the devil and should be avoided in good
APIs.
–Arthur
Received on 2019-08-29 09:41:36