web-dev-qa-db-fra.com

Instanciation explicite - quand est-elle utilisée?

Après quelques semaines de pause, j'essaie d'élargir et d'étendre ma connaissance des modèles avec le livre Modèles - Le guide complet par David Vandevoorde et Nicolai M. Josuttis, et ce que j'essaie de comprendre à ce moment est une instanciation explicite des modèles.

Je n'ai pas vraiment de problème avec le mécanisme en tant que tel, mais je ne peux pas imaginer une situation dans laquelle j'aimerais ou je voudrais utiliser cette fonctionnalité. Si quelqu'un peut m'expliquer cela, je serai plus que reconnaissant.

70

Copié directement de https://docs.Microsoft.com/en-us/cpp/cpp/explicit-instantiation :

Vous pouvez utiliser une instanciation explicite pour créer une instanciation d'une classe ou d'une fonction basée sur un modèle sans réellement l'utiliser dans votre code. Étant donné que cela est utile lorsque vous créez des fichiers de bibliothèque (.lib) qui utilisent des modèles pour la distribution, les définitions de modèle non fondées ne sont pas placées dans l'objet (.obj) des dossiers.

(Par exemple, libstdc ++ contient l'instanciation explicite de std::basic_string<char,char_traits<char>,allocator<char> > (lequel est std::string) donc à chaque fois que vous utilisez les fonctions de std::string, le même code de fonction n'a pas besoin d'être copié dans les objets. Le compilateur n'a qu'à référencer (lier) ceux-ci à libstdc ++.)

47
kennytm

Si vous définissez une classe de modèle que vous ne souhaitez utiliser que pour quelques types explicites.

Placez la déclaration de modèle dans le fichier d'en-tête comme une classe normale.

Mettez la définition du modèle dans un fichier source comme une classe normale.

Ensuite, à la fin du fichier source, instanciez explicitement uniquement la version que vous souhaitez être disponible.

Exemple idiot:

// StringAdapter.h
template<typename T>
class StringAdapter
{
     public:
         StringAdapter(T* data);
         void doAdapterStuff();
     private:
         std::basic_string<T> m_data;
};
typedef StringAdapter<char>    StrAdapter;
typedef StringAdapter<wchar_t> WStrAdapter;

La source:

// StringAdapter.cpp
#include "StringAdapter.h"

template<typename T>
StringAdapter<T>::StringAdapter(T* data)
    :m_data(data)
{}

template<typename T>
void StringAdapter<T>::doAdapterStuff()
{
    /* Manipulate a string */
}

// Explicitly instantiate only the classes you want to be defined.
// In this case I only want the template to work with characters but
// I want to support both char and wchar_t with the same code.
template class StringAdapter<char>;
template class StringAdapter<wchar_t>;

Principale

#include "StringAdapter.h"

// Note: Main can not see the definition of the template from here (just the declaration)
//       So it relies on the explicit instantiation to make sure it links.
int main()
{
  StrAdapter  x("hi There");
  x.doAdapterStuff();
}
67
Martin York

Cela dépend du modèle du compilateur - il y a apparemment le modèle Borland et le modèle CFront. Et cela dépend également de votre intention - si vous écrivez une bibliothèque, vous pourriez (comme mentionné ci-dessus) instancier explicitement les spécialisations que vous souhaitez.

La page GNU c ++ décrit les modèles ici https://gcc.gnu.org/onlinedocs/gcc-4.5.2/gcc/Template-Instantiation.html .

1
DAmann