Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Forward Declaration using for a template method

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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"

>Solution :

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> in a scope where Second::B is not a complete type. 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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading