Home > Enterprise >  Forward Declaration using for a template method
Forward Declaration using for a template method

Time:04-16

Why do I get an error when using a template method with a forward declared class? I don't actually need a definition of this class, only a declaration. Or maybe I have misunderstood how it actually works? Do I really need to include a corresponding .h file of class B?

Edited: And why then does forward declaration of class SomeInterface work with static_assert if I actually include "B.h"?

I want to achieve forward declaration to use template method without including ".h" files

Question after Kevin reply:

bar() method is actually needed for a Template Method Pattern, so there will be like a family of namespace Second. The problem is if I include more ".h" files from namespace Second, doesn't it be less optimized? This bar() method will be executed only once at start of the program

Example code:

// A.cpp
#include "A.h"

namespace Second
{
    class SomeInterface;
    class B;
}

namespace First
{
    class A
    {
    public:
        A() = default;

        template <typename M>
        void foo()
        {
            static_assert(std::is_base_of<Second::SomeInterface, M>::value, "You need to use SomeInterface or Derived from it");
        }

        void bar() // -- Template Method Pattern
        {
            foo<Second::B>(); // -- C2139   'Second::B': an undefined class is not allowed as
                      // an argument to compiler intrinsic type trait '__is_base_of'
            foo<Second::C>();
            foo<Second::D>();
            //...

        }
    };
}
// B.cpp
#include "B.h"
#include "SomeInerface.h"

namespace Second
{
    class B : public SomeInterface
    {
    public:
        B() = default;
    };
}

If I add this to the A.cpp then it will work fine

#include "B.h"

CodePudding user response:

Why do I get an error when using a template method with a forward declared class?

This is not generally a problem.

I don't actually need a definition of this class, only a declaration. Or maybe I have misunderstood how it actually works?

There is no general rule that template parameters need to be complete types, but there are specific cases, and yours is one of them.

Do I really need to include a corresponding .h file of class B?

In this case, yes.

And why then does forward declaration work with static_assert?

I'm not sure what you mean. The only static_assert in your code is in template method First::A::foo(). You get an error related to that static_assert (though not an assertion failure) when you instantiate the template with a certain template parameter. In what sense, then, do you think the behavior of the static_assert is inconsistent?

The basic problem here is that the std::is_base_of template requires its second type argument to be a complete type. This is in its specifications. A class type that is (only) forward-declared, with no definition in scope, is not complete. Therefore, you get an error when you instantiate First::A::foo<Second::B> at a point where no definition of Second::B is in scope. That error is recognized before the assertion can be evaluated, so the static_assert doesn't factor in except as the context of the error.

  • Related