Interface of a variant-like class I have created an NBT format reader (NBT is a binary serialization format that Minecraft uses to store its data). I made a node-like class that can be a data entry or the root of a subtree (that's how NBT is defined). The public interface of it currently looks like this:

class Tag
{
    Tag();

    void read(std::istream&amp; stream);
    void write(std::ostream&amp; stream);

    void print(int indent = 0);

    int8_t byteValue() const;
    int16_t shortValue() const;
    int32_t intValue() const;
    int64_t longValue() const;
    float floatValue() const;
    double doubleValue() const;
    ByteArray byteArrayValue() const;
    IntArray intArrayValue() const;
    UTF8String stringValue() const;
    std::vector&lt;Tag&gt; children() const;

    UTF8String name() const;
};


Is this the right design though? Originally I wanted to do the *Value methods with templates, but the problem is that the value of a Tag is dynamic, so that does not play nicely with the compile-time genericity.

Is it a blasphemy not to make the various types derived classes? I couldn't really take advantage of a virtual value method because the return types would need to differ. Is there a better way to implement a data structure like this? The aim is to make it easy to use and fast.
Couple of things I noticed:

The serialize members:

void read(std::istream&amp; stream);
void write(std::ostream&amp; stream);


I don't particular mind them but I also would prefer to have operator&lt;&lt; and operator&gt;&gt; defined (Note you can simply make these call write/read respectively).

With the stream iterators defined this becomes less useful.

void print(int indent = 0);


The following seem like very simialer.

int8_t byteValue() const;
int16_t shortValue() const;
int32_t intValue() const;
int64_t longValue() const;
float floatValue() const;
double doubleValue() const;
ByteArray byteArrayValue() const;
IntArray intArrayValue() const;
UTF8String stringValue() const;


I think we can replace all of them with:

template&lt;typename T&gt;
T const&amp; get() const;


I like this better as we do not need to guess that byte maps to int8_t or short maps to int16_t as we can explicitly get the type we want:

 int8_t  val = t.get&lt;int8_t&gt;();


But there is already something very similar defined in boost:

boost::any