2017-04-16 1 views
0

J'ai une fonction transpose déclarée dans un fichier d'en-tête global.h comme indiqué ci-dessous:C++ - Erreur « référence non définie » tout en utilisant des modèles avec fonction

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

La fonction est définie dans un autre fichier global.cpp comme indiqué ci-dessous:

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

Cependant, l'appel de fonction suivante:

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

jette l'erreur:

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

Le dim variable est définie à l'global.h comme indiqué ci-dessous:

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

je trouve this answer. Existe-t-il des moyens de conserver la définition de la fonction dans le global.cpp?

Modifier: J'ai lu le question dont cette question a été marquée comme doublon. Cela avec la réponse de @Xirema m'a aidé à réaliser que j'ai trois options: 1) Implémenter la fonction dans l'en-tête.

2) Implémenter la fonction dans un fichier avec l'extension '.ipp' et l'inclure dans l'en-tête.

3) La troisième option est instanciation explicite comme:

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

Lequel de ce qui précède est la meilleure méthode (je suis en train de suivre les meilleures pratiques de codage)?

Répondre

3

Les définitions de modèle ne peuvent pas avoir leur implémentation dans un fichier .cpp: il a besoin de pour être dans l'en-tête. Mais, si vous êtes une personne raisonnable et logique qui veut séparer la déclaration et la définition d'une fonction en deux fichiers différents, il existe une solution de rechange que vous pouvez utiliser. Mettez l'implémentation dans un fichier avec une extension de fichier que le compilateur ne reconnaîtra pas (un idiome commun doit utiliser .ipp), puis à la fin du fichier d'en-tête, ajoutez la ligne #include "impl.ipp" (ou n'importe quel nom de fichier aller avec). Cela permettra une utilisation correcte du modèle.

+0

Est-ce une mauvaise pratique de déplacer l'implémentation vers l'en-tête? De plus, si j'ai un fichier avec l'extension '.ipp' cela fonctionnera-t-il avec tous les compilateurs? Est-ce mieux que la méthode du fichier d'en-tête? –

+1

@skr_robo Ils n'ont pas besoin d'être dans un en-tête, mais si vous voulez partager l'implémentation entre plusieurs fichiers, l'implémentation doit être visible pour tous les utilisateurs. Un compilateur C++ ne se soucie pas de ce que vous nommez le fichier d'implémentation. Lorsqu'il repère une instruction '# include ', il recherche le fichier et le colle effectivement dans le fichier en cours de compilation. Vous pouvez inclure n'importe quel fichier syntaxiquement correct, y compris des astuces abusives qui chargent un fichier csv depuis Excel ou Matlab dans un tableau. Vous pouvez '# inclure 'des fichiers syntaxiquement incorrects si vous le souhaitez, mais le compilateur l'étouffera plus tard. – user4581301

+0

Okay. J'essaie de voir lequel est l'approche la plus professionnelle. S'il vous plaît voir la modification. –