Skip to content

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

@dutiona

Description

@dutiona

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions