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

Всъщност съм доста сигурен, че отговорът на моя проблем може да бъде намерен в една от създадените по-рано теми. По-специално, Къде и защо трябва да поставя ключовите думи за шаблона и името на типа?, което има страхотно обяснение за уточняването на двусмислеността на шаблон/име на тип. Аз обаче съм на загуба, защото всъщност не мога да разширя концепцията към моя код, който е шаблони на класове, които взаимодействат помежду си.

В тази тема мисля, че виждам същата грешка, каквато получавам в моя код. Защо отговорът е да се дефинира 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;

Вие създавате шаблонен клас с помощта на Class Template

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