I'm dealing with an application, that needs to read in 10+ CSV-files (of different kind) as input. The data is read into a container -- std::map
or vector
.
Previously each kind had its own parsing function, and I'm working on unifying that into a single templatized function: to have save on future code-maintenance and provide uniform error-reporting for broken files.
This function reads each line, discerns, whether the container type has the concept of a key
(like map
) and uses emplace
for those, and emplace_back
for the others (like vector
).
The only expectation from the value class of the container is that its constructor can instantiate from a CSV-line. Any exception by the constructor is a fatal error -- the input filename and line-number are reported, and the program exits:
try {
if constexpr (is_associative_container<Container>(NULL)) {
result->emplace(typename Container::key_type(
key, keylen), value);
} else {
result->emplace_back(value);
}
} catch (const std::exception &e) {
fprintf(stderr, "%s:%zd: %s\n", path, line, e.what());
goto failure;
}
This all works and I'm happy -- about 75% of the CSV-parsing is now done by this function.
I'm now facing the remaining quarter of the CSV-files, which are less straightforward: because certain rows in them require special treatment and their content isn't supposed to be stored in the container.
How can the value_type
's constructor signal to the function, that the exception it is throwing should not considered fatal? One way is to pick one of the standard exceptions (std::bad_function_call
?) as a signal, but that'd mean, the picked exception mustn't occur unexpectedly -- which is unreliable...
Anything else?