I'm writing a library of IO functions for my physics laboratory class. In the meanwhile, I'm hoping to learn more about generic programming and C++20 concepts.
Some context
I usually came home from the lab with a .txt file that looks like
value value value ...
value value value ...
where each line represents a set of repeated measurements of the same physical quantity.
I want to write a function that reads one line at a time from my .txt and put all the values it founds into some vector. My idea is to mock getline
The actual code
#include <algorithm> // for std::transform
#include <fstream> // for std::ifstream
#include <iterator> // for std::istream_iterator
#include <sstream> // for std::istringstream
#include <string> // for std::string and std::getline
#include <type_traits> // for std::is_arithmetic_v
#include <vector> // for std::vector
template<typename T> concept Arithmetic = std::is_arithmetic_v<T>;
namespace sf { namespace io {
template <Arithmetic T>
std::vector<T> getline(std::ifstream& data) {
std::vector<T> meas;
std::string line{};
while (line.size() == 0 && !data.eof()) {
std::getline(data, line);
}
std::istringstream lines{line};
std::istream_iterator<std::string> linei{lines};
std::transform(linei,
std::istream_iterator<std::string>{},
std::back_inserter(meas),
[] (std::string s) {return std::stod(s);});
return meas;
}
} } // namespace io // namespace sf
I.e., I first define a new concept for "arithmetic" types, and then I write a generic function that
- eats a file
- tries reading a line until we've got to an actual nonempty line or to
eof - parses whatever it got, and puts it into a
std::vector.
I'm planning to use my code like this
std::string path = "path/to/data.txt"
std::ifstream file(path);
auto meas1 = sf::io::getline<double>(file);
auto meas2 = sf::io::getline<double>(file);
// and so on
What I already know my code does not achieve
- First of all, I would like to make my code less dependent on the
vectorclass. - At some point I use the standard library's
stodfunction. There is at least another way of parsing number literals from strings to actual arithmetic types... but am I on the right path? I read that one could achieve exactly what I am trying to achieve, in a more idiomatic way, by the means of the>>operator...