从Template模板参数定义和推导参数

时间:2012-03-09 20:35:00

标签: c++

基于pp. 179

上的示例
template<template<typename T, typename A> class C, typename T, typename A>
                                                   ^^^^^^^^^^^^^^^^^^^^^^
void erase(C<T, A>&c, const T& item)
{
    c.erase(std::remove(c.begin(), c.end(), item), c.end());
}

int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
    list<int> lst;
    lst.push_back(42);
    erase(lst, 42);
}

如果我从typename T, typename A函数签名中删除erase,VS2010编译器会出现以下错误:

Error 1   error C2065: 'T' : undeclared identifier
Error 2   error C2065: 'A' : undeclared identifier
Error 3   error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Error 4   error C2143: syntax error : missing ',' before '&'

问题1 &GT;这些编译错误背后的原因是什么?

我们总是必须明确定义模板模板参数中使用的类型参数吗?

问题2 &GT;当我们调用以下行时,编译器如何推导出A的类型?

erase(lst, 42)

编译器是否真的根据A中定义的模板参数A的默认参数推断出类型list

请参阅list

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

类型Aallocator<T>

2 个答案:

答案 0 :(得分:8)

问题1

首先TAC的参数,而不是erase()模板的参数。因此,它们不可见,可见的是用^^^突出显示的第二个和第三个参数。请注意,第一个参数是一个typename / class,它是一个类模板。类模板本身不是类型,只有它的实例化。

为了更好地了解第一个TA如何不可见并且实际上没有扮演任何角色,您可以像这样重写它:

template<template<typename, typename> class C, typename T, typename A>

问题2

它可以推导A,因为lst传递为C<T, A>,因此Alst类型的类模板的第二个参数。

最后,您应该以不同的方式重写您的功能模板:

template <typename C>
void erase(C& c, const typename C::value_type& item)
{
    c.erase(std::remove(c.begin(), c.end(), item), c.end());
}

这样,您不会限制C模板参数的数量和含义。实际上,如果需要,此处C可以是非模板化类型。

答案 1 :(得分:1)

如果删除这些,则A和T仅在C的上下文中已知,而不是在erase()模板的上下文中。