Универсальные и обычные шаблоны (C++/CLI)

Универсальные и обычные шаблоны — это возможности языков программирования, обеспечивающие поддержку параметризированных типов. Однако они отличаются и имеют разные применения. В этом разделе дан обзор многих отличий.

Дополнительные сведения см. в статье Windows Runtime and Managed Templates (C++/CLI and C++/CX) (Среда выполнения Windows и управляемые шаблоны (C++/CLI и C++/CX)).

Сравнение обычных и универсальных шаблонов

Ниже перечислены основные различия между универсальными шаблонами и шаблонами языка C++.

  • Универсальные шаблоны универсальны до подстановки для них типов во время выполнения. Обычные шаблоны специализируются при компиляции, поэтому во время выполнения они еще не являются параметризованными типами.

  • Среда CLR специально поддерживает универсальные шаблоны в MSIL. Поскольку среда выполнения знает об универсальных шаблонах, при ссылке на сборку, содержащую универсальный тип, вместо универсального типа может подставляться конкретный тип. Обычные шаблоны, напротив, сводятся во время компиляции к обычным типам, и результирующие типы не могут специализироваться в других сборках.

  • Универсальные шаблоны, специализированные в двух разных сборках с одинаковыми аргументами типа, относятся к одному типу. Обычные шаблоны, специализированные в двух разных сборках с одинаковыми аргументами типа, среда выполнения считает относящимися к разным типам.

  • Универсальные шаблоны создаются в виде одного элемента исполняемого кода, который используется для всех аргументов ссылочного типа (это не относится к типам значений, имеющим уникальную реализацию для каждого типа значения). JIT-компилятор знает об универсальных шаблонах и может оптимизировать код для ссылочных типов или типов значений, которые используются в качестве аргументов типа. Обычные шаблоны создают отдельный код среды выполнения для каждой специализации.

  • Универсальные шаблоны не позволяют использовать параметры обычного шаблона, не являющиеся типами, например template <int i> C {}. Обычные шаблоны позволяют делать это.

  • Универсальные шаблоны не поддерживают явную специализацию (т. е. индивидуальную реализацию шаблона для конкретного типа). Обычные шаблоны поддерживают такую специализацию.

  • Универсальные шаблоны не поддерживают частичную специализацию (т. е. индивидуальную реализацию для подмножества аргументов типа). Обычные шаблоны поддерживают такую специализацию.

  • Универсальные шаблоны не позволяют использовать параметр типа в качестве базового класса для универсального типа. Обычные шаблоны поддерживают такую специализацию.

  • В отличие от универсальных шаблонов, обычные шаблоны поддерживают параметры шаблона template (например, template<template<class T> class X> class MyClass).

Объединение обычных и универсальных шаблонов

Основное различие в универсальных шаблонах имеет значение при создании приложений, объединяющих обычные и универсальные шаблоны. Например, предположим, что имеется шаблонный класс, для которого требуется создать универсальную оболочку с целью предоставления этого шаблона другим языкам в качестве универсального. Универсальный шаблон не может принимать параметр типа, передаваемый затем в обычный шаблон, поскольку обычный шаблон должен иметь этот параметр во время компиляции, но универсальный шаблон не разрешает его до выполнения. Разместить обычный шаблон внутри универсального нельзя, поскольку во время компиляции невозможно развернуть обычные шаблоны для произвольных универсальных типов, экземпляры которых могут создаваться во время выполнения.

Пример

Description

Ниже приведен простой пример совместного использования обычных и универсальных шаблонов. В этом примере шаблонный класс передает свой параметр универсальному типу. Обратное невозможно.

Эту идиому можно использовать, когда требуется выполнить сборку в существующем универсальном API с кодом шаблона, который является локальным для сборки C++/CLI, или при необходимости добавить слой параметризации к универсальному типу, чтобы воспользоваться некоторыми возможностями обычных шаблонов, не поддерживаемых универсальными шаблонами.

Код

// templates_and_generics.cpp
// compile with: /clr
using namespace System;

generic <class ItemType>
ref class MyGeneric {
   ItemType m_item;

public:
   MyGeneric(ItemType item) : m_item(item) {}
   void F() {
      Console::WriteLine("F");
   }
};

template <class T>
public ref class MyRef {
MyGeneric<T>^ ig;

public:
   MyRef(T t) {
      ig = gcnew MyGeneric<T>(t);
      ig->F();
    }
};

int main() {
   // instantiate the template
   MyRef<int>^ mref = gcnew MyRef<int>(11);
}
F

См. также

Универсальные шаблоны