It is often required for some non-scalar structure X
to provide input operator std::istream & operator >> (std::istream &, X &);
. I tried to implement it in a 3 slightly different ways:
#include <istream>
#include <ostream>
#include <tuple>
#include <cstddef>
struct rectangle
{
std::size_t l, t, r, b; // left, top, right, bottom
friend
std::istream &
operator >> (std::istream & in, rectangle & R)
{
#if 0
// v1
do {
if (!(in >> R.l)) {
break;
}
if (!(0 < R.l)) {
break;
}
if (!(in >> R.t)) {
break;
}
if (!(0 < R.t)) {
break;
}
if (!(in >> R.r)) {
break;
}
if (!(0 < R.r)) {
break;
}
if (!(in >> R.b)) {
break;
}
if (!(0 < R.b)) {
break;
}
return in;
} while (false);
in.setstate(std::ios::failbit);
return in;
#elif 0
// v2
if (in >> R.l) {
if (0 < R.l) {
if (in >> R.t) {
if (0 < R.t) {
if (in >> R.r) {
if (0 < R.r) {
if (in >> R.b) {
if (0 < R.b) {
return in;
}
}
}
}
}
}
}
}
in.setstate(std::ios::failbit);
return in;
#elif 0
// v3
if (!(in >> R.l)) {
return in;
}
if (!(0 < R.l)) {
in.setstate(std::ios::failbit);
return in;
}
if (!(in >> R.t)) {
return in;
}
if (!(0 < R.t)) {
in.setstate(std::ios::failbit);
return in;
}
if (!(in >> R.r)) {
return in;
}
if (!(0 < R.r)) {
in.setstate(std::ios::failbit);
return in;
}
if (!(in >> R.b)) {
return in;
}
if (!(0 < R.b)) {
in.setstate(std::ios::failbit);
return in;
}
return in;
#else
#error do select body!
#endif
}
friend
std::ostream &
operator << (std::ostream & out, rectangle const & R)
{
return out << R.l << ' ' << R.t << ' ' << R.r << ' ' << R.b;
}
bool
operator == (rectangle const & R) const
{
return std::tie(l, t, r, b) == std::tie(R.l, R.t, R.r, R.b);
}
};
// main.cpp
#include <iostream>
#include <sstream>
#include <cstdlib>
#ifdef NDEBUG
#undef NDEBUG
#endif
#include <cassert>
int
main()
{
std::stringstream ss;
rectangle lhs{1, 2, 3, 4};
ss << lhs;
rectangle rhs;
ss >> rhs;
assert(lhs == rhs);
return EXIT_SUCCESS;
}
Every way has its own advantages and disadvantages:
- v1:
- pros:
- plain code
- minimal duplication of code (1
setstate()
) - just two
return
statements
- cons:
- (semantically)
goto
-likedo {} while (false);
construction (is it really a bad practice?)
- (semantically)
- pros:
- v2:
- pros:
- minimal duplication of code (1
setstate()
) - just two
return
statements
- minimal duplication of code (1
- cons:
- too deep nesting of
if
statements
- too deep nesting of
- pros:
- v3 (naive):
- pros:
- plain code
- cons:
- duplication of code (
setstate()
euqal to number of constituents) - plenty of
return
statements
- duplication of code (
- pros:
I like v1 way, but are there better patterns to implement operator >>
?
Aucun commentaire:
Enregistrer un commentaire