0

I'm trying to parse a Wavefront OBJ file. If line describes a vertex, i try to split it, take XYZ-coordinates, and assign them to a tuple. For example, if the line is "v -0.000581696 -0.734665 -0.623267 1.0", the result must be {-0.000581696, -0.734665, -0.623267}. The code is as follows:

const auto vertex = ranges::views::split(line, " "sv) |
                    ranges::views::tail | // ignore "v "
                    ranges::views::take(3) | // ignore 4th value if exists
                    ranges::views::transform([](const std::string &value) { return std::stof(value); }) | // convert string to float
                    ranges::to<std::tuple<float, float, float>>();

However, the compiler gives me this error:

error C2678: binary '|': no operator found which takes a left-hand operand of type 'ranges::take_view<ranges::tail_view<ranges::split_view<ranges::ref_view<std::string>,std::basic_string_view<char,std::char_traits<char>>>>>' (or there is no acceptable conversion)

What am I doing wrong and how do I fix it?

EDIT: Inserting ranges::views::transform([](const auto &view) { return view | ranges::to<std::string>; }) between take and transform solved the string conversion part, but using to<std::tuple> still leads to an error

error C2678: binary '|': no operator found which takes a left-hand operand of type 'ranges::transform_view<ranges::transform_view<ranges::take_view<ranges::tail_view<ranges::split_view<ranges::ref_view<std::string>,std::basic_string_view<char,std::char_traits<char>>>>>,Arg>,`anonymous-namespace'::readWavefrontObj::<lambda_2>>' (or there is no acceptable conversion)

So far, I could only convert this to vector<float>. Is conversion to a tuple even possible?

henker
  • 1
  • 1

1 Answers1

0

ranges::to requires the type have an (Iterator, Iterator) constructor, which std::tuple doesn't have.

You'll have to explicitly take the first 3 elements, e.g.

template <std::random_access_range R>
std::array<float, 3> to_array(R r) {
    assert(ranges::size(r) >= 3);
    return { r[0], r[1], r[2] };
}

const auto vertex = to_array(ranges::views::split(line, " "sv) |
                             ranges::views::tail | // ignore "v "
                             ranges::views::transform([](const std::string &value) { return std::stof(value); })); // transform is lazy, so it doesn't matter what else is on line
Caleth
  • 52,200
  • 2
  • 44
  • 75