Reading three rows of six tab-separated numbers I've just posted this solution in my review of @adrienlucca's question, which is to read three rows of six tab-separated doubles.

#include &lt;fstream&gt;
#include &lt;iostream&gt;
#include &lt;string.h&gt;
#include &lt;vector&gt;

struct Sexdoublet {
    double x, y, d, m, c, t;

    friend std::istream &amp;operator&gt;&gt;(std::istream &amp;in, Sexdoublet &amp;r) {
        return in &gt;&gt; r.x &gt;&gt; r.y &gt;&gt; r.d &gt;&gt; r.m &gt;&gt; r.c &gt;&gt; r.t;
    }

    friend std::ostream &amp;operator&lt;&lt;(std::ostream &amp;out, const Sexdoublet &amp;r) {
        return out &lt;&lt; "[ x = " &lt;&lt; r.x
                   &lt;&lt; ", y = " &lt;&lt; r.y
                   &lt;&lt; ", d = " &lt;&lt; r.d
                   &lt;&lt; ", m = " &lt;&lt; r.m
                   &lt;&lt; ", c = " &lt;&lt; r.c
                   &lt;&lt; ", t = " &lt;&lt; r.t &lt;&lt; " ]";
    }
};

std::vector&lt;Sexdoublet&gt; import(std::istream &amp;in) {
    std::vector&lt;Sexdoublet&gt; data;
    Sexdoublet s;
    do {
        in &gt;&gt; s;
    } while (in &amp;&amp; (data.push_back(s), true));
    return data;
}

int main(int argc, char *argv[]) {
    // If the first command-line argument is not "-", treat it as the filename
    // from which to read the input.  Otherwise, read from STDIN.
    const char *filename = (argc &gt;= 2 &amp;&amp; 0 != strcmp("-", argv[1])) ?
                                argv[1] : NULL;
    std::ifstream f;
    std::istream &amp;in = filename ? (f.open(filename), f) : std::cin;
    if (!f) {
        std::cerr &lt;&lt; "Error opening " &lt;&lt; filename &lt;&lt; ": "
                  &lt;&lt; strerror(errno) &lt;&lt; std::endl;
        return 1;
    }

    std::vector&lt;Sexdoublet&gt; data = import(in);
    std::for_each(data.begin(), data.end(), [](const Sexdoublet &amp;s) {
        std::cout &lt;&lt; s &lt;&lt; std::endl;
    });
    return 0;
}


I ended up using the comma operator twice — both times as a "workaround" for the fact that a function I call returns void:


(data.push_back(s), true) — I have to check whether the istream extractions succeeded before adding an element to the result.
(f.open(filename), f) — I like the ternary operator because it expresses the fact that in is going to be assigned to one value or another.  Also, the in reference has to be initialized immediately and irrevocably, right?


It is my impression that the comma operator is rarely used in C and C++.  So, I'd like to ask, are these reasonable uses of the comma operator?  Or too clever?  Or too dumb, because I've missed an entirely better solution?
the first use can be replaced with:

while(in &gt;&gt; s) {
    data.push_back(s)
}


the second case is much more readable with a simple if else:

std::ifstream f;
if(argc &gt;= 2 &amp;&amp; 0 != strcmp("-", argv[1])) {
    f.open(argv[1]);
    if (!f) {
        std::cerr &lt;&lt; "Error opening " &lt;&lt; argv[1] &lt;&lt; ": "
                  &lt;&lt; strerror(errno) &lt;&lt; std::endl;
        return 1;
    }

}
std::istream &amp;in = f.is_open() ? f : std::cin;