1

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;
}
Jonny Schubert
  • 1,393
  • 2
  • 18
  • 39

1 Answers1

3

In your specific case, you can't. You could do a explicit template instantiation in your .cpp for some values of the non-type template argument T. If you use those values everywhere in the rest of your program, you would be OK. However, I assume that this is not what you want, and want to be free to specify any value for T. If that is the case, you have to put the definition of your template in some place that is accessible for the users of your template(usually in the .h) file.

What some people do, just for the sake of readability, is to put the definitions of templates into a .inl file, that is included as the last line of the .h that declares the template. This does not change in any way the restriction, just provides you with some separation. If you were to ship this as a library, you would need to provide your clients with your .h as well as your .inl files.

If you want to do the explicit instantiation, it would look like this, in your cpp:

template class B<20>;

Then, you could use the class B if you're using it only in the version with 20 as the non-type template argument (any other value would result in the same error you're currently seeing)

divinas
  • 1,787
  • 12
  • 12