фабричный шаблон — с шаблонами

#c #templates

#c #шаблоны

Вопрос:

У меня есть следующее в заголовке ядра третьей стороны, который я бы предпочел не трогать:

 template<typename Iterator_T>
struct Tree
{
    template<typename Node_T>
    struct TypedNode;

    struct AbstractNode
    {
        AbstractNode(Iterator_T t)
        {
            ...
        }

        template<typename Rule_T>
        TypedNode<Rule_T>* NewChild()
        {
            TypedNode<Rule_T>* ret = new TypedNode<Rule_T>(this);
            AddChild(ret);
            return ret;
        }

        template<typename T>
        TypedNode<T>* GetFirstTypedChild();
    };

    template<typename Node_T>
    struct TypedNode : AbstractNode
    {
        ...
    };

    template<typename Rule_T, typename ParserState_T>
    void CreateNode(ParserState_Tamp; p)
    {
        current = current->template NewChild<Rule_T>();
    }
};

template<typename Node_T>
struct TreeBuilder
{
    Tree<Iterator_T> tree;

    template<typename Rule_T>
    void CreateNode()
    {
        tree.CreateNode<Rule_T>(*this);
    }
};
  

и хотел бы добавить подкласс TypedNode в дерево с дополнительными методами и членами. Есть ли чистый способ сделать это без рефакторинга исходного кода? Я думаю, что суть проблемы заключается в:
TypedNode* ret = новый TypedNode(этот);

Похоже, что он мог бы использовать фабрику, возможно, специализируя создание экземпляра шаблона TypedNode и включая заголовок перед базовыми заголовками. Что-то вроде:

 template<>
struct Tree<const char*>::TypedNode<SpecificRuleType>
{
    ...
};
  

Но это не удается, жалуясь на «слишком мало списков шаблонов-параметров». Возможно, что-то тривиальное, но мой <template-fu> немного заржавел :>(. Любые идеи будут оценены!

Ответ №1:

Оба Tree и TypedNode являются шаблонами, ваша специализация должна быть:

 template<> // for Tree<...>
template<> // for TypedNode<...>
struct Tree<const char*>::TypedNode<SpecificRuleType>
{
    ...
};
  

Комментарии:

1. Еще раз.. время ожидания окна редактирования истекло. <enter> настаивает на отправке комментария в этом браузере! Спасибо — это помогло обойти ошибку. К сожалению, быстро выскочила другая жалоба на: current = current-> template newChild<Rule_T>(pos), в которой говорится, что он не может преобразовать дерево<const char*>::TypedNode<SpecificRuleType>* в дерево<const char*>::AbstractNode * в присваивании. TypedNode является подклассом AbstractNode, но, возможно, это связано с тем, что в первом объявлении TypedNode не указано, что он наследуется от AbstractNode.

2. Неважно.. существует альтернативный подход, который позволяет избежать всего этого шаблонного фуу. Даже если бы я заставил его работать, я подозреваю, что перенос его на другой компилятор может быть приключением, и проблема довольно тривиальна. Спасибо за вашу помощь!