Skip to content

How to derive writers from each other

Raymond Chen edited this page Apr 1, 2019 · 1 revision

The writer_base class uses CRTP to permit the base writer_base<T> class to access overloads of the write method implemented by the derived class. This technique, however, interferes with class derivation.

struct simple_writer : writer_base<simple_writer>
{
   // Knows how to write a Foo and a Bar.
   void write(Foo const& foo);
   void write(Bar const& bar);
};

struct sparkle_writer : simple_writer
{
   // Also knows how to print a Baz.
   void write(Baz const& baz);

   // Customize how Foo is written.
   void write(Foo const& foo) {
     begin_sparkle();
     simple_writer::write(foo);
     end_sparkle();
   }
};

This doesn't work because simple_writer derives from writer_base<simple_writer>, so the only thing that writer_base knows how to write is things supported by simple_writer. It won't know how to write Baz objects, and it will write Foo objects the simple way, not the sparkly way.

To work around this problem, you need to use CRTP in the simple writer.

template<typename T>
struct simple_writer : writer_base<T>
{
   // Knows how to write a Foo and a Bar.
   void write(Foo const& foo);
   void write(Bar const& bar);
};

struct sparkle_writer : simple_writer<sparkle_writer>
{
   // Also knows how to print a Baz.
   void write(Baz const& baz);

   // Customize how Foo is written.
   void write(Foo const& foo) {
     begin_sparkle();
     simple_writer::write(foo);
     end_sparkle();
   }
};
Clone this wiki locally