16.1.3 Parâmetros do modelo
Muitas vezes definimos o nome do parâmetro como T, mas na verdade podemos usar qualquer nome
tal como
template <typename DATA>using partNo = BlobA<DATA>;
Parâmetros de modelo e regras de escopo. O intervalo utilizável de um nome de parâmetro de modelo é após sua declaração e antes do final da declaração ou definição do modelo. Como qualquer outro nome, os parâmetros do modelo ocultam o mesmo nome declarado no escopo externo. No entanto, como na maioria dos outros contextos, os nomes dos parâmetros do modelo não podem ser reutilizados dentro dos modelos:
typedef double A;
template <typename A,typename B>void f(A a,B b)
{
A tmp = a;
double B;//错误重复声明模板参数B
}
Como o nome de tipo B de B foi declarado acima, o tipo de B foi declarado abaixo.
Observe também que o tipo de temp não é duplo, é o tipo de parâmetro real do modelo
Declaração de modelo:
A declaração do modelo deve conter parâmetros do modelo
template <typename T> int compare(const T&, const T&);
template <typename T> class Blob;
Tal como acontece com as funções, o nome do modelo na declaração não precisa ser o mesmo de quando foi definido
template <typename T> T calc(const T&,const T&);
template <typename U> U calc(const U&,const U&);
Por exemplo, essas duas funções de modelo são realmente as mesmas, portanto, haverá definições duplicadas.
Use membros do tipo de classe
Por exemplo, podemos usar string :: size_type, sabemos o tipo de string, mas para o modelo T :: mem, não sabemos o tipo de T
Por padrão, a linguagem C ++ assume que o nome acessado por meio do operador de escopo não é um tipo. Portanto, se quisermos usar um membro de tipo de um parâmetro de tipo de modelo, devemos informar explicitamente ao compilador que o nome é um tipo. Conseguimos isso usando typename.
template <typename T>
typename T::value_type top(const T&c)
{
if(!c.empty())
return c.back();
else
return typename T::value_type();
}
Nossa função superior espera um argumento de tipo de contêiner. Ela usa typename para indicar o tipo de retorno e gera um elemento inicializado por valor para retornar ao chamador quando não há elemento em c.
Então olhamos para o código
int main()
{
int b;
std::vector<int> vec;
top(vec);
// std::cout<<partNo<int>::count()<<std::endl;
return 0;
}
Se vec for passado, ele está correto. Se a for passado porque é um int, ele está errado. Isso tudo graças ao fato de que informamos o compilador com antecedência.