Modelos (C++)Templates (C++)

Os modelos são a base para a programação genérica em C++.Templates are the basis for generic programming in C++. Como uma linguagem fortemente tipada, C++ exige que todas as variáveis para ter um tipo específico, explicitamente declarado pelo programador ou deduzido pelo compilador.As a strongly-typed language, C++ requires all variables to have a specific type, either explicitly declared by the programmer or deduced by the compiler. No entanto, muitos algoritmos e estruturas de dados têm a mesma aparência independentemente do tipo que estejam operando em.However, many data structures and algorithms look the same no matter what type they are operating on. Os modelos habilitam a definir as operações de uma classe ou função e permitir que o usuário especifique quais concreto tipos essas operações deve trabalhar em.Templates enable you to define the operations of a class or function, and let the user specify what concrete types those operations should work on.

Definindo e usando modelosDefining and using templates

Um modelo é uma construção que gera um tipo comum ou uma função em tempo de compilação com base nos argumentos que o usuário fornece para os parâmetros de modelo.A template is a construct that generates an ordinary type or function at compile time based on arguments the user supplies for the template parameters. Por exemplo, você pode definir um modelo de função como esta:For example, you can define a function template like this:

template <typename T>
T minimum(const T& lhs, const T& rhs)
{
    return lhs < rhs ? lhs : rhs;
}

O código acima descreve um modelo para uma função genérica com um único parâmetro de tipo T, cujo valor de retorno e parâmetros (lhs e rhs) da chamada são todos esses tipos.The above code describes a template for a generic function with a single type parameter T, whose return value and call parameters (lhs and rhs) are all of this type. Você pode nomear um parâmetro de tipo que é semelhante, mas, por convenção único letras maiusculas do alfabeto é mais comumente usados.You can name a type parameter anything you like, but by convention single upper case letters are most commonly used. T é um parâmetro de modelo; a typename palavra-chave diz que esse parâmetro é um espaço reservado para um tipo.T is a template parameter; the typename keyword says that this parameter is a placeholder for a type. Quando a função é chamada, o compilador substituirá todas as instâncias de T com o argumento de tipo concreto que é especificado pelo usuário ou deduzido pelo compilador.When the function is called, the compiler will replace every instance of T with the concrete type argument that is either specified by the user or deduced by the compiler. O processo no qual o compilador gera uma classe ou função de um modelo é conhecida como instanciação do modelo; minimum<int> é uma instanciação do modelo minimum<T>.The process in which the compiler generates a class or function from a template is referred to as template instantiation; minimum<int> is an instantiation of the template minimum<T>.

Em outro lugar, um usuário pode declarar uma instância do modelo que é especializada em int. Suponha que get_a() e get_b() são funções que retornam um int:Elsewhere, a user can declare an instance of the template that is specialized for int. Assume that get_a() and get_b() are functions that return an int:

int a = get_a();
int b = get_b();
int i = minimum<int>(a, b);

No entanto, como esse é um modelo de função e o compilador podem deduzir o tipo de T argumentech um e b, você pode chamá-lo como uma função comum:However, because this is a function template and the compiler can deduce the type of T from the arguments a and b, you can call it just like an ordinary function:

int i = minimum(a, b);

Quando o compilador encontra a última instrução, ele gera uma nova função na qual cada ocorrência de T no modelo é substituído pelo int:When the compiler encounters that last statement, it generates a new function in which every occurrence of T in the template is replaced with int:

int minimum(const int& lhs, const int& rhs)
{
    return lhs < rhs ? lhs : rhs;
}

As regras para como o compilador executa a dedução de tipo em modelos de função são com base nas regras de funções comuns.The rules for how the compiler performs type deduction in function templates are based on the rules for ordinary functions. Para obter mais informações, consulte sobrecarregar resolução de modelo de chamadas de função.For more information, see Overload Resolution of Function Template Calls.

Parâmetros de tipoType parameters

No minimum modelo acima, observe que o parâmetro de tipo T não está qualificada de forma alguma até que ele seja usado nos parâmetros da chamada de função, em que a constante e qualificadores de referência são adicionados.In the minimum template above, note that the type parameter T is not qualified in any way until it is used in the function call parameters, where the const and reference qualifiers are added.

Não há nenhum limite prático para o número de parâmetros de tipo.There is no practical limit to the number of type parameters. Separe vários parâmetros por vírgulas:Separate multiple parameters by commas:

template <typename T, typename U, typename V> class Foo{};

A palavra-chave classe é equivalente a typename neste contexto.The keyword class is equivalent to typename in this context. Você pode expressar o exemplo anterior, como:You can express the previous example as:

template <class T, class U, class V> class Foo{};

Você pode usar o operador de reticências (...) para definir um modelo que pega um número arbitrário de zero ou mais parâmetros de tipo:You can use the ellipses operator (...) to define a template that takes an arbitrary number of zero or more type parameters:

template<typename... Arguments> class vtclass;

vtclass< > vtinstance1;
vtclass<int> vtinstance2;
vtclass<float, bool> vtinstance3;

Qualquer tipo interno ou definido pelo usuário pode ser usado como um argumento de tipo.Any built-in or user-defined type can be used as a type argument. Por exemplo, você pode usar std:: Vector na biblioteca padrão para armazenar inteiros, duplicatas, cadeias de caracteres, MyClass, MyClass const *, MyClass &.For example, you can use std::vector in the Standard Library to store ints, doubles, strings, MyClass, const MyClass*, MyClass&. A principal restrição ao usar os modelos é que um argumento de tipo deve oferecer suporte a todas as operações que são aplicadas aos parâmetros de tipo.The primary restriction when using templates is that a type argument must support any operations that are applied to the type parameters. Por exemplo, se nós chamarmos mínimo usando MyClass, como neste exemplo:For example, if we call minimum using MyClass as in this example:

class MyClass
{
public:
    int num;
    std::wstring description;
};

int main()
{
    MyClass mc1 {1, L"hello"};
    MyClass mc2 {2, L"goodbye"};
    auto result = minimum(mc1, mc2); // Error! C2678
}

Será gerado um erro do compilador porque MyClass não oferece uma sobrecarga para o < operador.A compiler error will be generated because MyClass does not provide an overload for the < operator.

Não há nenhum requisito de inerente que os argumentos de tipo para qualquer modelo específico para todos os pertencerem à mesma hierarquia de objeto, embora seja possível definir um modelo que impõe uma restrição.There is no inherent requirement that the type arguments for any particular template all belong to the same object hierarchy, although you can define a template that enforces such a restriction. Você pode combinar técnicas orientadas a objeto com modelos; Por exemplo, você pode armazenar um derivado * em um vetor<Base*>.You can combine object-oriented techniques with templates; for example, you can store a Derived* in a vector<Base*>. Observe que os argumentos devem ser ponteirosNote that the arguments must be pointers

vector<MyClass*> vec;
   MyDerived d(3, L"back again", time(0));
   vec.push_back(&d);

   // or more realistically:
   vector<shared_ptr<MyClass>> vec2;
   vec2.push_back(make_shared<MyDerived>());

Os requisitos básicos que impõem de vetor e outros contêineres da biblioteca padrão nos elementos de T é que T ser atribuível a cópia e construível por cópia.The basic requirements that vector and other standard library containers impose on elements of T is that T be copy-assignable and copy-constructible.

Parâmetros sem tipoNon-type parameters

Ao contrário de tipos genéricos em outras linguagens como c# e Java, os modelos de C++ dão suporte a parâmetros sem tipo, também chamados de parâmetros de valor.Unlike generic types in other languages such as C# and Java, C++ templates support non-type parameters, also called value parameters. Por exemplo, você pode fornecer um valor inteiro constante para especificar o comprimento de uma matriz, assim como acontece com este exemplo, que é semelhante à classe std:: array na biblioteca padrão:For example, you can provide a constant integral value to specify the length of an array, as with this example that is similar to the std::array class in the Standard Library:

template<typename T, size_t L>
class MyArray
{
    T arr[L];
public:
    MyArray() { ... }
};

Observe a sintaxe na declaração de modelo.Note the syntax in the template declaration. O valor de size_t é passado como um argumento de modelo em tempo de compilação e deve ser constante ou uma expressão constexpr.The size_t value is passed in as a template argument at compile time and must be constant or a constexpr expression. Você pode usá-lo assim:You use it like this:

MyArray<MyClass*, 10> arr;

Outros tipos de valores, incluindo ponteiros e referências podem ser passados como parâmetros sem tipo.Other kinds of values including pointers and references can be passed in as non-type parameters. Por exemplo, você pode passar um ponteiro para uma função ou um objeto de função para personalizar algumas operação dentro do código de modelo.For example, you can pass in a pointer to a function or function object to customize some operation inside the template code.

Modelos como parâmetros de modeloTemplates as template parameters

Um modelo pode ser um parâmetro de modelo.A template can be a template parameter. Neste exemplo, MyClass2 tem dois parâmetros de modelo: um parâmetro typename T e um parâmetro de modelo Arr:In this example, MyClass2 has two template parameters: a typename parameter T and a template parameter Arr:

template<typename T, template<typename U, int I> class Arr>
class MyClass2
{
    T t; //OK
    Arr<T, 10> a;
    U u; //Error. U not in scope
};

Porque o Arr próprio parâmetro não tem nenhum corpo, seus nomes de parâmetro não são necessários.Because the Arr parameter itself has no body, its parameter names are not needed. Na verdade, é um erro para fazer referência a Arrdo typename ou classe de nomes de parâmetros de dentro do corpo de MyClass2.In fact, it is an error to refer to Arr's typename or class parameter names from within the body of MyClass2. Por esse motivo, Arrdo nomes de parâmetro de tipo podem ser omitidos, conforme mostrado neste exemplo:For this reason, Arr's type parameter names can be omitted, as shown in this example:

template<typename T, template<typename, int> class Arr>
class MyClass2
{
    T t; //OK
    Arr<T, 10> a;
};

Argumentos de modelo padrãoDefault template arguments

Modelos de classe e a função podem ter argumentos padrão.Class and function templates can have default arguments. Quando um modelo tem um argumento padrão que você pode deixá-lo não for especificado quando você usá-lo.When a template has a default argument you can leave it unspecified when you use it. Por exemplo, o modelo de std:: Vector tem um argumento padrão para o alocador:For example, the std::vector template has a default argument for the allocator:

template <class T, class Allocator = allocator<T>> class vector;

Na maioria dos casos a classe std:: allocator padrão é aceitável, para que você use um vetor como este:In most cases the default std::allocator class is acceptable, so you use a vector like this:

vector<int> myInts;

Mas se necessário você pode especificar um alocador personalizado da seguinte maneira:But if necessary you can specify a custom allocator like this:

vector<int, MyAllocator> ints;

Para mais argumentos de modelo, todos os argumentos após o primeiro argumento padrão devem ter argumentos padrão.For multiple template arguments, all arguments after the first default argument must have default arguments.

Ao usar um modelo cujos parâmetros são padronizados, use colchetes angulares vazios:When using a template whose parameters are all defaulted, use empty angle brackets:

template<typename A = int, typename B = double>
class Bar
{
    //...
};
...
int main()
{
    Bar<> bar; // use all default type arguments
}

Especialização de modeloTemplate specialization

Em alguns casos, não é possível ou desejável para um modelo definir exatamente o mesmo código para qualquer tipo.In some cases, it isn’t possible or desirable for a template to define exactly the same code for any type. Por exemplo, você pode desejar definir um caminho de código a ser executado somente se o argumento de tipo for um ponteiro ou um std:: wstring, ou um tipo derivado de uma classe base específica.For example, you might wish to define a code path to be executed only if the type argument is a pointer, or a std::wstring, or a type derived from a particular base class. Nesses casos, você pode definir um especialização do modelo para esse tipo específico.In such cases you can define a specialization of the template for that particular type. Quando um usuário cria uma instância do modelo com esse tipo, o compilador usa a especialização para gerar a classe e para todos os outros tipos, o compilador escolhe o modelo mais geral.When a user instantiates the template with that type, the compiler uses the specialization to generate the class, and for all other types, the compiler chooses the more general template. Especializações em que são especializados em todos os parâmetros são concluir especializações.Specializations in which all parameters are specialized are complete specializations. Se apenas alguns dos parâmetros são especializadas, ele é chamado uma especialização parcial.If only some of the parameters are specialized, it is called a partial specialization.

template <typename K, typename V>
class MyMap{/*...*/};

// partial specialization for string keys
template<typename V>
class MyMap<string, V> {/*...*/};
...
MyMap<int, MyClass> classes; // uses original template
MyMap<string, MyClass> classes2; // uses the partial specialization

Um modelo pode ter qualquer número de especializações desde que cada parâmetro de tipo especializado é exclusivo.A template can have any number of specializations as long as each specialized type parameter is unique. Somente modelos de classe podem ser parcialmente especializados.Only class templates may be partially specialized. Todas as especializações parciais e completas de um modelo devem ser declaradas no mesmo namespace que o modelo original.All complete and partial specializations of a template must be declared in the same namespace as the original template.

Para obter mais informações, consulte especialização de modelo.For more information, see Template Specialization.