Parsing positive integers from CSV file
Some couple nits.


You function read_line does not what it suggests. It reads a file line by line. So you should find an appropriate name.
Your choice of uint_fast8_t/uint_fast16_t is interesting given that your example csv table hold some larger values. Have you measured the impact vs unsigned int or std::size_t. Be aware that modern cpu can read multiple elements at once so you choice might actually have negative impact.
Every line you clear numbers and build it up again. It will be beneficial to just initialize it once via resize and then just overwrite the old value. That way you can omit the unnecessary clear
Getline takes a third argument which is the delemiter. Also getline stops at newline and end of file so you dont need all that error checking Given that you now the number of entries per line you can simply loop and accumulate

while (infile.good()) {
    for (auto&amp;&amp; elem : numbers) {
        std::getline(infile, buffer, ",");
        elem = 0;
        for (auto&amp;&amp; digit : buffer) {
            elem *= 10;
            elem += (digit - '0');
        }
    }
    callback(numbers);
}



If you want to be sure you can check getline and return if its bad.

    while (infile.good()) {
        for (auto&amp;&amp; elem : numbers) {
            if (!std::getline(infile, buffer, ",")) {
                return;
            }
            elem = 0;
            for (auto&amp;&amp; digit : buffer) {
                elem *= 10;
                elem += (digit - '0');
            }
        }
        callback(numbers);
    }