switch from completely separate member functions to overloaded "write" functions, to better match Visitor pattern
remove one unnecessary default implementation
use variadic templates to concisely generate the default overloaded write() methods