0

I want to split my template classes into 2 files like how normal classes function with a .hpp where the declaration is and an .ipp where the implementation lives.

I have got this working with normal methods. But with methods that are themselves templates I am facing some issues.

Using the following structure:

#ifndef MATRIX_HPP
#define MATRIX_HPP

#include <array>
#include <type_traits>

template<typename t,
         std::size_t m,
         std::size_t n>
class Matrix
{

static_assert(std::is_arithmetic<t>::value,
                  "Matrix can only be declared with a type where std::is_arithmetic is true.");
public:
    Matrix();

    template<std::size_t y, std::size_t x, std::size_t p, std::size_t q>
    Matrix<t, p, q> slice() const;

private:
    std::array<std::array<t, n>, m> data{};
};

#include "Matrix.ipp"

#endif

Matrix.ipp:

#include "Matrix.hpp"

template<typename t, std::size_t m, std::size_t n>
Matrix<t, m, n>::Matrix()
{}

template<typename t,
         std::size_t m,
         std::size_t n,
         std::size_t y,
         std::size_t x,
         std::size_t p,
         std::size_t q>
Matrix<t, p, q> Matrix<t, m, n>::slice() const
{
    auto mat = Matrix<t, p, q>();

    for (std::size_t i = y; i < m; i++)
    {
        for (std::size_t j = x; j < n; j++)
        {
            mat[i - y][j - x] = (*this)[i][j];
        }
    }

    return mat;
}

main.cpp

#include "Matrix.hpp"

int main() {
    auto m = Matrix<3, 3, int>();
    auto sliced = m.template slice<1, 1, 2, 2>();

    return 0;
}

Now when I compile this it fails with the following message:

../Matrix.ipp:14:17: error: prototype for ‘Matrix<t, p, q> Matrix<t, m, n>::slice() const’ does not match any in class ‘Matrix<t, m, n>’
 Matrix<t, p, q> Matrix<t, m, n>::slice() const
                 ^~~~~~~~~~~~~~~
In file included from ../main.cpp:0:0:
../Matrix.hpp:20:18: error: candidate is: template<class t, long unsigned int m, long unsigned int n> template<long unsigned int y, long unsigned int x, long unsigned int p, long unsigned int q> Matrix<t, p, q> Matrix<t, m, n>::slice() const
  Matrix<t, p, q> slice() const;

I am not sure how to handle this since the compiler won't recognize it. Is there a way to fix this?

I hope somebody can help me. Thanks!

  • @user0042 It isn't My method above works for normal methods. Only template methods aren't working. –  Dec 05 '17 at 18:40
  • @user0042 The problem is not the missing inclusion of the definition. The header includes the ".ihh" file. The problem is providing two sets of template arguments at the point of definition. – François Andrieux Dec 05 '17 at 18:40
  • @JohnSmith See the duplicate I linked. You need to provide two distinct `template` argument sets when you define your function. You cannot combine them into a single larger set of template arguments. – François Andrieux Dec 05 '17 at 18:41

1 Answers1

0

You need to define two sets of template parameters: one for matrix class template, and another for matrix class function, not merging them into one long list:

template<typename t, std::size_t m, std::size_t n>
template<std::size_t y, std::size_t x, std::size_t p, std::size_t q>
Matrix<t, p, q> Matrix<t, m, n>::slice() const
{

Also note that your includes are actually messed up. Including "Matrix.hpp" into .ipp file won't work because you are already including "Matrix.ipp" from "Matrix.hpp". Though this won't lead to an error.

user7860670
  • 35,849
  • 4
  • 58
  • 84