Prinz Km
Prinz Km

Reputation: 323

How to forward declare a class template?

I'm trying to implement the specification pattern.In that, I have a specification abstract class and an overloaded && operator which returns AndSpecification, which is actually derived from Specification class.Now I have the problem of circular dependency b/w AndSpecification and Specification.Specification is a class template so is AndSpecification.

Specification.h

//#include "AndSpecification.h"- this creates a problem
template <class T>
class Specification
{
 public:
     Specification()
     {

     }

     virtual ~Specification()
     {

     }
     virtual bool isSatisfied(T *item)=0;
     AndSpecification<T>  operator&&(Specification &other)
     {
         return AndSpecification<T>(*this,other);
     }
};

AndSpecification.h

#include "Specification.h"

template <class T>

class AndSpecification : public Specification<T>
{
    Specification <T> *first;
    Specification <T> *second;
public:
    AndSpecification(Specification <T> *first,Specification <T> * second);

    // Specification interface
public:
    bool isSatisfied(T *item) override;
};

A help would be appreciated. full code:https://github.com/princekm/specification.git

Upvotes: 0

Views: 194

Answers (3)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122458

Instead of forward declaration (see other answers) you can consider that Specification does not necessarily need to know about AndSpecification. I mean, its a template anyhow. If you add a template template parameter to Specifiacation like this:

template <class T,template<typename> class X>
class Specification
{
 public:
     Specification()
     {

     }

     virtual ~Specification()
     {

     }
     virtual bool isSatisfied(T *item)=0;
     X<T>  operator&&(Specification &other)
     {
         return X<T>(*this,other);
     }
};

Then only when you instantiate it you need to know both:

 #include "Specification.h"
 #incldue "AndSpecification.h"
 template <typename T>
 using Specification_with_And = Specification<T,AndSpecification>;

Upvotes: 0

Jarod42
Jarod42

Reputation: 217275

You need forward declaration, and move definition of your method which need both class definition after those classes:

// Specification.h
#pragma once
template <class T> class AndSpecification;

template <class T>
class Specification
{
 public:
     Specification() {}

     virtual ~Specification() {}
     virtual bool isSatisfied(T *item)=0;
     AndSpecification<T>  operator&&(Specification &other);
};

#include "Specification.inl"
// AndSpecification.h
#pragma once

#include "Specification.h"
template <class T>
class AndSpecification : public Specification<T>
{
    Specification <T> *first;
    Specification <T> *second;
public:
    AndSpecification(Specification <T> *first,Specification <T> * second);

    // Specification interface
public:
    bool isSatisfied(T *item) override;
};
// Specification.inl
#pragma once
#include "Specification.h"
#include "AndSpecification.h"
template <class T>
AndSpecification<T>  Specification<T>::operator&&(Specification &other)
{
    return AndSpecification<T>(this, &other);
}

Demo

Upvotes: 1

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36401

Forward declare it:

template <class T> AndSpecification;

The following is correct (by removing the pure virtual method for the example):

template <class T> class AndSpecification;
template <class T>
class Specification
{
 public:
     Specification()
     {

     }

     virtual ~Specification()
     {

     }
//     virtual bool isSatisfied(T *item)=0;
     AndSpecification<T>  operator&&(Specification &other)
     {
         return AndSpecification<T>(*this,other);
     }
};
template <class T>

class AndSpecification : public Specification<T>
{
    Specification <T> *first;
    Specification <T> *second;
public:
    AndSpecification(Specification <T> *first,Specification <T> * second);

    // Specification interface
public:
    bool isSatisfied(T *item) override;
};

class A{};

int main() {
    Specification<A> a;
}

Upvotes: 0

Related Questions