These files supply four standard global I/O channels for the CoCoA
library. These channels mimic the global channels present in the C++
STL: cin
, cout
, cerr
, and clog
.
The current choices for these four channels can be obtained by calling these functions (inside namespace CoCoA):
std::istream& GlobalInput(); std::ostream& GlobalOutput(); std::ostream& GlobalErrput(); std::ostream& GlobalLogput();
By default the standard global I/O channels for the CoCoA library are the corresponding ones of the standard C++ library. Alternative choices may be specified by calling these functions (see *NOTE*)
std::istream& SetGlobalInput(std::istream& in); std::ostream& SetGlobalOutput(std::ostream& out); std::ostream& SetGlobalErrput(std::ostream& err); std::ostream& SetGlobalLogput(std::ostream& log);
In each case the value returned is the previous istream/ostream associated with that channel.
*NOTE* the procedures for changing the settings of the global i/o streams maintain a reference to the value supplied. If you use a local variable as argument, make sure that its value is not destroyed before you have finished i/o on it. See the example program ex-io.C.
void InputFailCheck(const std::istream& in, const char* const FnName);
This function simply checks that the stream in
is in a good state;
if not, it throws an ERR::InputFail
indicating the function name FnName
.
The implementation could hardly be simpler.
As recommended in Meyers's book I have put the globals in an anonymous
namespace. I chose to use plain pointers for the global variables
InPtr
, OutPtr
, ErrPtr
and LogPtr
; references are unsuitable because
they cannot be reseated in C++, and auto_ptr
is unsuitable because
we do not want to own the streams. I do not believe that there can be
problems with race-conditions when these four global variables are
initialized since we use only the addresses of std::cin
, etc.
However, there could be race-condition problems with subsequent
changes to the values.
The names GlobalInput
etc are rather cumbersome. It is also annoying to
have to call them as functions. I could use automatic type conversions
to eliminate the need for the "()"s -- I'll wait until people start
complaining. Suggestions for better names are welcome.
Another reason for having a new class to represent GlobalOutput
etc. is
that the template for printing std::list
s and std::vector
s could easily
clash with a user's definition of operator<<
.
It is tempting to make the simple functions in io.C into inline functions, but inlining is tricky with the global variables in an anonymous namespace. And anyway the minor gain in performance will easily be swamped by the high costs of actually conducting I/O; so making them inline would really be quite pointless.
It would be nice to avoid the potential pitfalls of dangling references, but I do not currently see how to achieve this.