namespace Meta__
{
    template <Tag__ tag>
    struct TypeOf;

    template <typename Tp_>
    struct TagOf;

$insert polymorphicSpecializations

        // The Base class: 
        // Individual semantic value classes are derived from this class.
        // This class offers a member returning the value's Tag__
        // and two member templates get() offering const/non-const access to
        // the actual semantic value type.
    class Base
    {
        Tag__ d_tag;
    
        protected:
            Base(Tag__ tag);

        public:
            Base(Base const &other) = delete;

            Tag__ tag() const;
    
            template <Tag__ tg_>
            typename TypeOf<tg_>::type &get();

            template <Tag__ tg_>
            typename TypeOf<tg_>::type const &get() const;
    };

        // The class Semantic is derived from Base. It stores a particular
        // semantic value type. 
    template <Tag__ tg_>
    class Semantic: public Base
    {
        typedef typename TypeOf<tg_>::type DataType;
    
        DataType d_data;
    
        public:
                // The constructor forwards arguments to d_data, allowing
                // it to be initialized using whatever constructor is
                // available for DataType
            template <typename ...Params>
            Semantic(Params &&...params);

            DataType &data();
            DataType const &data() const;
    };

        // If Type is default constructible, Initializer::value is
        // initialized to new Type, otherwise it's initialized to 0, allowing
        // struct SType: public std::shared_ptr<Base> to initialize its
        // shared_ptr<Base> class whether or not Base is default
        // constructible.
    template <bool constructible, typename Type>
    struct Initializer
    {
        static Type *value;
    };
    template <bool constructible, typename Type>
    Type *Initializer<constructible, Type>::value = new Type;
    
    template<typename Type>
    struct Initializer<false, Type>
    {
        static constexpr Type *value = 0;
    };

        // The class Stype wraps the shared_ptr holding a pointer to Base.
        // It becomes the polymorphic STYPE__
        // It also wraps Base's get members, allowing constructions like
        // $$.get<INT> to be used, rather than $$->get<INT>.
        // Its operator= can be used to assign a Semantic *
        // directly to the SType object. The free functions (in the parser's
        // namespace (if defined)) semantic__ can be used to obtain a 
        // Semantic *. 
    struct SType: public std::shared_ptr<Base>
    {
        SType();

        template <typename Tp_>
        SType &operator=(Tp_ &&value);

        Tag__ tag() const;

            // this get()-member checks for 0-pointer and correct tag 
            // in shared_ptr<Base>, and resets the shared_ptr's Base * 
            // to point to Meta::__Semantic<tg_>() if not
        template <Tag__ tg_>
        typename TypeOf<tg_>::type &get();
        template <Tag__ tg_>
        typename TypeOf<tg_>::type const &get() const;

            // the data()-member does not check, and may result in a 
            // segfault if used incorrectly
        template <Tag__ tg_>
        typename TypeOf<tg_>::type &data();
        template <Tag__ tg_>
        typename TypeOf<tg_>::type const &data() const;

        template <Tag__ tg_, typename ...Args>
        void emplace(Args &&...args);
    };

}  // namespace Meta__


