Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chaining view::transform 3 times with one transform2 fails to compile with gcc #996

Closed
dutiona opened this issue Jan 21, 2019 · 0 comments
Closed
Labels

Comments

@dutiona
Copy link

dutiona commented Jan 21, 2019

Hello,

I've encontered an issue when trying to compile a simple use case with gcc 8.2. I have the following code:

std::vector<int> buff(12, -1);
::ranges::span<int> sp(buff.data(), 12);

auto x = ::ranges::view::transform(sp, [](int a) { return a > 3 ? a : 42; });
auto y = ::ranges::view::transform(x, sp, [](int a, int b) { return a + b; });
auto rng = ::ranges::view::transform(y, [](int a) { return a + 1; });

The last line fails to compile with gcc 8.2 and issue the following error:

/.../.conan/data/range-v3/0.4.0/ericniebler/stable/package/e52aec0ecc24318bcb1daf3dc03e2f3e38ea6e23/include/range/v3/view/transform.hpp:280:73: error:
could not convert ‘{((const ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >*)this)->ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >::fun_, ranges::v3::CPOs::begin.ranges::v3::_begin_::fn::operator()<const ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> > >(((const ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >*)this)->ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >::rng1_), ranges::v3::CPOs::begin.ranges::v3::_begin_::fn::operator()<const ranges::v3::span<int> >(((const ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >*)this)->ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >::rng2_)}’
from ‘<brace-enclosed initializer list>’
to
‘ranges::v3::iter_transform2_view<ranges::v3::transform_view<ranges::v3::span<int>, Range_range_transform2_read_chain_Test::TestBody()::<lambda(int)> >, ranges::v3::span<int>, ranges::v3::indirected<Range_range_transform2_read_chain_Test::TestBody()::<lambda(int, int)> > >::cursor’
                 return {fun_, ranges::begin(rng1_), ranges::begin(rng2_)};

(full stack in attachment)
error_full.txt

When I've investigated a little bit further, I tried to change the code of view::transform:

CONCEPT_REQUIRES(Range<Rng1 const>() && Range<Rng2 const>())
cursor begin_cursor() const
{
    return {fun_, ranges::begin(rng1_), ranges::begin(rng2_)};
}

by:

CONCEPT_REQUIRES(Range<Rng1 const>() && Range<Rng2 const>())
cursor begin_cursor() const
{
    iterator_t<Rng2> it2 = ranges::begin(rng2_);
    iterator_t<Rng1> it1 = ranges::begin(rng1_);
    return {fun_, it1, it2};
}

Now I get this error:

/.../.conan/data/range-v3/0.4.0/ericniebler/stable/package/e52aec0ecc24318bcb1daf3dc03e2f3e38ea6e23/include/range/v3/view/transform.hpp:278:53:
error: conversion from
‘basic_iterator<adaptor_cursor<[...],adaptor<true>>>’
to non-scalar type
‘basic_iterator<adaptor_cursor<[...],adaptor<false>>>’ requested
                 iterator_t<Rng1> it1 = ranges::begin(rng1_);
                                        ~~~~~~~~~~~~~^~~~~~~

(full stack in attachment)
error_full2.txt

After investigating the conversion constructors, it seems that basic_iterator explicitly have one, adaptor too, but I didn't see one for adaptor_cursor (except for a using base_t::base_t, but maybe it is not even needed for adaptor_cursor since there are no members). As for why the "const" boolean is true in one case and false in the other, I don't know (bad deduction/overload somewhere ?)

Clang7 seems to compile it so I don't know if it is a compiler bug or a library bug.

You can find a live repro on godbolt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants