Sebastian
Sebastian

Reputation: 795

C++ range-v3: trying to chain together transforms

I'm completely new to the range library, so I shouldn't be surprised that this code isn't compiling and I cannot figure out why:

#include <iostream>
#include <algorithm>
#include <fstream>
#include <iterator>
#include <vector>

#include <range/v3/all.hpp>
#include <range/v3/view/all.hpp>
using namespace ranges::v3;


std::ifstream open_file(const std::string &filename) {
    return std::ifstream{filename};
}

int count_lines(std::ifstream &in) {
    return std::count(std::istreambuf_iterator<char>{in},
                      std::istreambuf_iterator<char>{}, '\n');
}

std::vector<int>
count_lines_in_files(const std::vector<std::string> &filenames) {
    auto a1 = filenames | view::transform(open_file) | view::transform(count_lines);
    return a1;
}

int main() {
    const std::vector<std::string> files{"listing1_1.cpp",
                                         "listing1_2.cpp",
                                         "listing1_4.cpp",
                                         "listing1_5.cpp"};
    const auto result = count_lines_in_files(files);
    std::cout << ranges::view::all(result) << '\n';
}

It appears that the complaint is about a1, which the compiler tells me "error: variable has incomplete type 'void'."

Can someone see what I'm doing wrong, or tell me how to properly chain these together if possible?

Thanks in advance!

Upvotes: 2

Views: 840

Answers (2)

Bob__
Bob__

Reputation: 12749

As noted by Porsche9II, "std::ifstream doesn't have a copy constructor". You can find more on this topic here:

Why are iostreams not copyable?

C++11 introduced a move constructor (6) for std::basic_ifstream, so you could write

auto open_file(const std::string &filename) {
    return std::ifstream{filename};
}

auto count_lines(std::ifstream &&in) {
    return std::count(std::istreambuf_iterator<char>{in},
                      std::istreambuf_iterator<char>{}, '\n');
}

Testable HERE.

Upvotes: 3

Porsche9II
Porsche9II

Reputation: 651

std::ifstream doesn't have a copy constructor - returning std::ifstream by a function is not a good idea. One possible solution: opening and counting should take place in one function.

Upvotes: 3

Related Questions