Взаимодействие с шаблоном класса

На самом деле я совершенно уверен, что ответ на мою проблему можно найти в одной из ранее созданных тем. В частности, Где и почему я должен помещать ключевые слова шаблона и имени типа? в котором есть отличное объяснение устранения неоднозначности шаблона/имени типа. Однако я в недоумении, потому что на самом деле я не могу расширить концепцию своего кода, который представляет собой шаблоны классов, которые взаимодействуют друг с другом.

В этом потоке, я думаю, я вижу ту же ошибку, что и в моем коде. Почему ответ заключается в определении typedef с использованием A<B>, где B — класс, а не A<T>, где T — шаблон имени типа, который мы действительно хотим иметь.

Тем не менее, я пробовал эти варианты безрезультатно. Вот код. Спасибо за помощь.

#include "testTemplateA.h"
template<typename A>
class testTemplateB {
public:
    // none of these work
    typedef testTemplateA<A> templateType;
    typedef typename testTemplateA<A> templateType;
    typedef typename testTemplateA<testTemplateB> templateType;

    testTemplateB(templateType& TA) {}

    ~testTemplateB(void) {}
};

#include "testTemplateB.h"
template<typename A>
class testTemplateA
{
public:
    testTemplateA(void) {}

    ~testTemplateA(void) {}

    void callUponB(void) {
        testTemplateB<A> g = testTemplateB<A>(this);
    }



};

person user3417339    schedule 22.03.2014    source источник


Ответы (2)


Это больше похоже на проблему циклической зависимости, чем на проблему синтаксиса шаблона. Пока вы можете определить один класс с другим незавершенным, вы можете сделать что-то вроде:

// Begin testTemplateA.h
#ifndef TEST_TEMPLATE_A_H
#define TEST_TEMPLATE_A_H

template<typename A>
class testTemplateA
{
public:
    testTemplateA(void) {}

    ~testTemplateA(void) {}

    void callUponB(void); // Can't be defined here!
};

#include "testTemplateB.h"

template<typename A>
void testTemplateA<A>::callUponB(void) {
    testTemplateB<A> g = testTemplateB<A>(this);
}

#endif
// End testTemplateA.h

// Begin testTemplateB.h
// Yes, the include is outside the define guard.
#include "testTemplateA.h"

#ifndef TEST_TEMPLATE_B_H
#define TEST_TEMPLATE_B_H

template<typename A>
class testTemplateB {
public:
    typedef testTemplateA<A> templateType;

    testTemplateB(templateType& TA) {}

    ~testTemplateB(void) {}
};

#endif
// End testTemplateB.h

Если исходный файл включает только testTemplateA.h, он увидит определение шаблона класса для testTemplateA, затем включит все содержимое testTemplateB.h, а затем увидит определения элементов в testTemplateA.h, которые зависят от testTemplateB. Если исходный файл включает только testTemplateB.h, он сразу же начнется с testTemplateA.h, который по-прежнему будет включать testTemplateB.h в середине и даст те же результаты. Если исходный файл включает оба в любом порядке, второй не будет иметь никакого эффекта, так как оба уже включены.

Вам нужно только такое ключевое слово typename перед именем, которое включает хотя бы один токен ::.

И еще одно: ваш конструктор testTemplateB(templateType& TA); ожидает ссылку, но ваш оператор testTemplateB<A> g = testTemplateB<A>(this); передает значение указателя this.

person aschepler    schedule 22.03.2014
comment
Как только я прочитал циркулярное упоминание, я подумал про себя, что он, вероятно, содержит ответ, и я думаю, что так оно и есть. Однако, если позволите, мне могут понадобиться дополнительные пояснения. Разделение прототипа и фактического метода разделено аналогично тому, что будет делать файл заголовка/объекта, но мне сказали, что нельзя использовать такой стиль при использовании шаблонов классов. Вы хотите объяснить, почему это разрешено в этом случае? - person user3417339; 22.03.2014
comment
@ user3417339: Вы можете определить член шаблона класса (или член шаблона) вне класса. Он просто должен быть в заголовочном файле, который включается, а не в исходном файле, который не виден другим исходным файлам. - person aschepler; 22.03.2014

Проблема здесь

typedef testTemplateA<A> templateType;

Вы создаете класс шаблона, используя шаблон класса

template<typename A>
class testTemplateA

При создании класса шаблона вам необходимо указать фактический тип. Так и должно быть,

typedef testTemplateA<< testTemplateB<int >> templateType;

Рекомендуется использовать "class", если ожидается, что T всегда будет классом, с "typename", если могут использоваться другие типы (int, char*, float). быть ожидаемым. Считайте это подсказкой по использованию.

person Dipika    schedule 22.03.2014
comment
Нет, testTemplateA<A> является допустимым типом (который зависит от параметра шаблона A). - person aschepler; 22.03.2014
comment
Соглашаться!! Но из-за круговой зависимости это давало ошибку времени компиляции. - person Dipika; 22.03.2014