0

I have a function transpose declared in a header file global.h as shown below:

template <size_t M, size_t N>
extern void transpose(array <array <float, N>, M>&, array <array <float, M>, N>&);

The function is defined in another file global.cpp as shown below:

template <size_t M, size_t N>
void transpose(array <array <float, N>, M>& a, array <array <float, M>, N>& b)
{
    // This can be made faster
    for (size_t i = 0; i < M; i++)
    {
        for (size_t j = 0; j < N; j++)
        {
            b[j][i] = a[i][j];
        }
    }
}

However, the following function call:

transpose<dim, dim>(jacobian, jacobian_transposed);

throws the error:

undefined reference to `void transpose<23u, 23u>(std::array<std::array<float, 23u>, 23u>&, std::array<std::array<float, 23u>, 23u>&)'

The variable dim is defined in the global.h as shown below:

static constexpr const int marker_num = 10;
static constexpr const int dim = (2 * marker_num) + 3;

I found this answer. Are there any ways to keep the function definition in the global.cpp?

Edit: I read the question of which this question was marked as duplicate. That along with the answer from @Xirema helped me realize that I have three options: 1) Implement function in the header.

2) Implement function in a file with '.ipp' extension and include it inside the header.

3) Third option is explicit instantiations like:

template <size_t M, size_t N>
void transpose(array <array <float, N>, M>& a, array <array <float, M>, N>& b)
{
    // This can be made faster
    for (size_t i = 0; i < M; i++)
    {
        for (size_t j = 0; j < N; j++)
        {
            b[j][i] = a[i][j];
        }
    }
}
template void transpose(array <array <float, dim>, dim>& a, array <array <float, dim>, dim>& b);
template void transpose(array <array <float, dim>, 2>& a, array <array <float, 2>, dim>& b);

Which of the above is the best method (I am trying to follow the best coding practice)?

Community
  • 1
  • 1
skr
  • 914
  • 3
  • 18
  • 35

1 Answers1

3

Template definitions cannot have their implementation in a .cpp file: it needs to be in the header.

But, if you're a reasonable, logical person who wants to separate the declaration and definition of a function into two different files, there is a work-around you can use.

Put the implementation in a file with a file extension the compiler won't recognize (a common idiom is to use .ipp), and then at the end of the header file, add the line #include "impl.ipp" (or whatever filename you go with). This will enable correct use of the template.

Xirema
  • 19,889
  • 4
  • 32
  • 68
  • Is it considered a bad practice to move the implementation to header? Also, if I have a file with `.ipp` extension will it work with all compilers? Is this better than the header file method? – skr Apr 16 '17 at 19:40
  • 1
    @skr_robo They do not *need* to be in a header, but if you are going to share the implementation across multiple files, the implementation must be visible to all users. A C++ compiler does not care what you name the implementation file. When it spots a `#include` statement, it looks for the file and effectively pastes it into the file being compiled. You can `#include` any syntactically correct file, including some abusive tricks that load a csv file from Excel or Matlab into an array. You can `#include` syntactically incorrect files if you want to, but the compiler will choke over it later. – user4581301 Apr 16 '17 at 19:55
  • Okay. I am trying to see which one is more professional approach. Please see the edit. – skr Apr 16 '17 at 20:02