2009-08-06 11 views
1

Je sais que la question n'est pas très descriptive mais je ne pourrais pas la formuler mieux.Comment se débarrasser de l'avertissement LNK4006 lorsque vous n'utilisez pas de modèles?

Je suis en train de compiler une bibliothèque liée statique qui a plusieurs objets, tous les objets contiennent les éléments suivants:

#include foo.h 

foo.h est quelque chose le long de ces lignes:

#pragma once 
template<class T> 
class DataT{ 
    private: 
     T m_v; 
    public: 
     DataT(T v) : m_v(v){} 
}; 

typedef DataT<double> Data; 

maintenant , tout fonctionne bien, mais si je change DataT pour être simplement Data avec double au lieu de T, j'obtiendrai un avertissement LNK4006 au moment de la liaison pour chaque .obj indiquant que le .ctor était déjà défini.

Edit 1:

#pragma once 

class Data{ 
    private: 
     double m_v; 
    public: 
     Data(double v) : m_v(v){} 
}; 

Edit 2: J'utilise MSVC7. Le .ctor est en fait inclus dans les deux cas comme dans

... 
public: 
    Data(double v); 

#include foo.inl 
... 
//foo.inl 
Data::Data(double v): m_v(v) {} 

Ce que je suis en train d'accomplir bien, est de ne pas avoir ce compilable mais comme en-tête, l'utilisateur peut utiliser.

+2

Pouvez-vous montrer à quoi ressemble le code modifié? – gatorfax

+0

Quel compilateur exact utilisez-vous? Le code est-il vraiment tel que vous le publiez? (En particulier, est-ce que le constructeur est défini dans le corps de la classe? Ou est-il défini à l'extérieur de la définition de la classe? Ceci est particulièrement important). Comme Mike a commenté: Si vous avez des problèmes avec un code particulier, postez le code qui vous donne des problèmes pas un autre code qui compile parfaitement. Ma conjecture est que vous définissez le constructeur à l'intérieur du .h mais en dehors de la classe. –

+0

Maintenant, pouvez-vous montrer comment l'en-tête et la classe Data sont utilisés? L'en-tête affiché fonctionne correctement. Tous les fichiers .cpp sont-ils recompilés? –

Répondre

2

Je ne suis pas sûr de ce que vous essayez de faire dans l'exemple pour modifier # 2, mais je pense que cela pourrait aider si vous avez les éléments suivants dans foo.inl:

inline 
Data::Data(double v): m_v(v) {} 

Si le contenu de foo.inl est également inclus dans quelque chose où le mot-clé inline ne fonctionnera pas ou ne devrait pas être, vous pouvez probablement utiliser le préprocesseur pour gérer la différence en utilisant une macro qui se développe à rien ou inline selon le cas.

+0

Je ne sais pas comment il va éviter l'avertissement de déjà défini. – Anzurio

+0

Le mot-clé 'inline' indique au compilateur C++ qu'il est autorisé à être défini plusieurs fois (les fonctions inline ne sont pas soumises à la "règle de définition unique"). De la norme, "Chaque programme doit contenir exactement une définition de chaque fonction non-inline ou objet qui est utilisé dans ce programme, aucun diagnostic requis.La définition peut apparaître explicitement dans le programme, il peut être trouvé dans la norme ou un bibliothèque définie par l'utilisateur ou (le cas échéant) implicitement définie (voir 12.1, 12.4 et 12.8) Une fonction inline doit être définie dans chaque unité de traduction dans laquelle elle est utilisée. " –

+0

Oh mon dieu, tu es un génie, ça a marché !! Merci! – Anzurio

1

Si vous définissez la définition du constructeur dans foo.cpp au lieu de foo.h, elle ne sera pas compilée séparément dans chaque unité de traduction. Au moment où une copie du constructeur est compilée dans chaque objet contient le foo.h inclure.

L'autre solution possible serait d'obtenir le compilateur pour aligner le constructeur. avez-vous désactivé l'inlining dans les paramètres du compilateur? Le constructeur semble assez facile pour s'introduire automatiquement.

+0

Cela semble prometteur :). Je vais l'essayer. – Anzurio

+1

Mais cela ne devrait pas poser de problème puisque la définition est en ligne, ce qui est autorisé en C++ (et doit être supporté par le compilateur et les outils) –

+0

Ce n'est pas vrai avec le code affiché. Ce serait le cas si le constructeur était défini en dehors de la définition de classe (en dehors des accolades) mais pas tel qu'il est écrit. –