2017-04-16 78 views
0

我有在头文件global.h声明的函数transpose,如下所示:C++ - 错误“未定义参考”,而使用模板与功能

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

功能在另一个文件global.cpp定义如下所示:

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]; 
     } 
    } 
} 

但是,下面的函数调用:

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

引发错误:

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

可变dimglobal.h定义如下所示:

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

我发现this answer。是否有保持在global.cpp函数定义的任何方式?

编辑:我看了question其中这个问题被标记为重复。这与@Xirema答案一起帮助我意识到我有三种选择: 1)实施头功能。

2)在与“.ipp”扩展名的文件实现的功能和包括它的报头的内部。

3)第三种选择是明确的实例,如:

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); 

这上面是最好的方法(我试图遵循最佳的编码做法)?

回答

3

模板定义不能在.cpp文件中实现:它的需要位于标题中。

但是,如果你是谁想要一个函数的声明和定义分成两个不同的文件合理的,合乎逻辑的人,有一种变通方法,您可以使用。

将实现放入一个带有文件扩展名的文件中,编译器不会识别(一个常见的习惯用法是使用.ipp),然后在头文件末尾添加行#include "impl.ipp"(或任何文件名去)。这将启用模板的正确使用。

+0

是它被认为是不好的做法,移动实施头?另外,如果我有'.ipp'扩展名的文件,将它与所有的编译器工作?这比头文件方法更好吗? –

+1

@skr_robo他们不需要将*置于页眉中,但如果要跨多个文件共享实现,则实现必须对所有用户都可见。一个C++编译器不关心你命名实现文件。当它发现一个'#include'语句时,它会查找该文件并将其有效地粘贴到正在编译的文件中。你可以'#include'任何语法正确的文件,包括一些从Excel或Matlab载入csv文件到数组中的滥用技巧。如果你愿意,你可以'#include'语法不正确的文件,但编译器稍后会扼杀它。 – user4581301

+0

好的。我试图看看哪一种更专业。请参阅编辑。 –