Question

I am actually fairly certain the answer to my problem can be found in one of the previously created threads. In particular, Where and why do I have to put the "template" and "typename" keywords? which has a great explanation on template/typename disambiguation. I am however at a loss because I am not actually able to extend the concept to my code which is class templates that interact with each other.

In this thread, I think I see the same error as I get in my code. Why is the answer to define the typedef using A<B> where B is the class, as opposed to A<T> where T is the typename template we actually want to have.

Nevertheless, I have tried these options to no avail. Here is the code. Thank you for your help.

#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);
    }



};
Was it helpful?

Solution

This looks more like a circular dependency problem than a template syntax problem. As long as you can define one class with the other incomplete, you can do something like:

// 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

If a source file includes just testTemplateA.h, it will see the class template definition for testTemplateA, then include the entire contents of testTemplateB.h, then see the member definitions in testTemplateA.h that depend on testTemplateB. If a source file includes just testTemplateB.h, it will immediately begin with testTemplateA.h, which will still include testTemplateB.h in the middle and get the same results. If a source file includes both in either order, the second one will have no effect since both have already been included.

You only need the typename keyword like that in front of a name including at least one :: token.

One other thing: your constructor testTemplateB(templateType& TA); expects a reference, but your statement testTemplateB<A> g = testTemplateB<A>(this); passes the pointer value this.

OTHER TIPS

Problem is here

typedef testTemplateA<A> templateType;

You are creating a template class using Class Template

template<typename A>
class testTemplateA

While creating a template class you need to give actual type. So it should be like this,

typedef testTemplateA<< testTemplateB<int >> templateType;

It is adviced to use "class" if it is expected T will always be a class, with "typename" if other types (int, char*, float whatever) may be expected. Consider it a usage hint.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top