I would like to hide my function taking a template parameter reference in the corresponding cpp file using C++11. But I always end up in a missing reference linker error. It only obviously works if I copy the definition to a.h file but I want to hide the code. Otherwise using a template object as parameter forces me to put a lot of my project code to the header file. Is there any way to archive this?
Related to: Storing C++ template function definitions in a .CPP file. But here the template is typename not a size.
This is my minimal example showing my problem.
b.h
#ifndef _B_EXAMPLE_H
#define _B_EXAMPLE_H
#include <cstdint>
#include <cstring>
template<std::uint32_t T>
class B
{
private:
    char x[T];
public:
    void add(const char* str)
    {
        strncpy(this->x, str, T - 1);
    }
};
#endif
a.h
#ifndef _A_EXAMPLE_H
#define _A_EXAMPLE_H
#include "b.h"
#include <cstdint>
class A
{
public:
    template<std::uint32_t T> void foo(B<T>& t);
};
#endif
a.cpp
#include "a.h"
template<std::uint32_t T> void A::foo(B<T>& obj)
{
    obj.add("Top secret");
}
main.cpp
#include "a.h"
int main()
{
    B<20> bObj;
    A aObj;
    aObj.foo(bObj);
    return 1;
}
Edit
Even If this question has already been closed I would like to share my solution here. In my opinion my question is related but not the same.
b.h
#ifndef _B_EXAMPLE_H
#define _B_EXAMPLE_H
#include <cstdint>
#include <cstring>
class B
{
private:
    char* const x;
    const std::uint32_t xLen;
public:
    B(char* x, std::uint32_t len) : x(x), xLen(len) {}
    virtual ~B() {}
    void add(const char* str)
    {
        strncpy(this->x, str, this->xLen - 1);
    }
};
template<std::uint32_t T>
class GenB : public B
{
    public:
        char myBuf[T];
        GenB() : B(myBuf, T) {}
};
#endif
a.h
#ifndef _A_EXAMPLE_H
#define _A_EXAMPLE_H
#include "b.h"
#include <cstdint>
class A
{
public:
    void foo(B& t);
};
#endif
a.cpp
#include "a.h"
void A::foo(B& obj)
{
    obj.add("Top secret");
}
main.cpp
#include "a.h"
int main()
{
    GenB<20> bObj;
    A aObj;
    aObj.foo(bObj);
    return 1;
}
 
    