推断模板参数类型,模板类与模板函数

时间:2016-04-17 21:28:10

标签: c++ stl set

我已经为具有指针对象的set定义了一个删除器,但是当我以下面的方式定义它并不工作并且说 在函数' int main()':41:43:错误:在'之前缺少模板参数('令牌在/usr/include/c++/4.9/set中包含的文件: 这就是我使用Deleter

的路线
template <typename T>
struct Deleter
{
  void operator () (T *ptr)
  {
     delete ptr;
  }
};

但是当我改变了模板声明的位置,如下所示,它开始工作。

struct Deleter1
{
  template <typename T>
  void operator () (T *ptr)
  {
     delete ptr;
  }
};

任何人都可以解释究竟是什么区别。因为当我们声明一个具有模板变量的类或者甚至是具有模板参数的函数时,我们在类定义之前声明模板声明。

4 个答案:

答案 0 :(得分:1)

当您使用函数模板时,编译器通常可以从调用函数的方式来判断模板参数必须是什么。所以在这样的电话中

Deleter1 d1;
int *ip = new int;
d1(ip);

编译器推断Tint

对于使用第一个代码的相应代码,您需要编写

Deleter d;
int *ip = new int;
d(ip);

请注意,在定义d时,编译器无法知道d()将使用int*调用。

答案 1 :(得分:0)

  

任何人都可以解释究竟是什么区别

第一个是类模板。模板的实例是具有成员函数的类。

int* silly_int = new int;
float* silly_float = new float;
Deleter<int> d;    // Deleter<int> is a class
d(silly_int);      // it can delete int pointers using the member function
Deleter<float> d2; // Deleter<float> is another class
d2(silly_float);   // it can delete float pointers

第二个是具有成员函数模板的类。模板的实例是成员函数。

Deleter1 d3;      // Deleter1 is a class
d3(silly_int);    // it too can delete int pointers 
d3(silly_float);  // and pointers of other types as well
                  // using different instance of the member function template

答案 2 :(得分:0)

使用您的第一个类型Deleter,您可以创建接受固定类型的对象。

// del_int only accepts int pointers
Deleter<int> del_int;
// del_string only accepts std::string pointers
Deleter<std::string> del_string;

int* ip = new int;
std::string* sp = new std::string;

del_int(ip);    // ok
del_string(sp); // ok
del_int(sp);    // error
del_string(ip)  // error

但是使用Deleter1,您可以创建单个对象,并且它将接受任何指针,因为其成员operator()是模板化的。

// del_any will accept any kind of pointer
Deleter1 del_any;

int* ip = new int;
std::string* sp = new std::string;

del_any(ip); // ok
del_any(sp); // ok

答案 3 :(得分:0)

第一个在struct上有模板参数,并且创建结构,编译器需要知道它为什么类型创建结构。由于我们使用的是没有参数的默认构造函数,编译器无法推断出类型,因此需要明确指定它,即

Deleter<Foo>()

然后编译器使用operator()函数创建一个'Foo Deleter'结构,该函数只接受Foo *类型的参数。

第二个版本定义了一个具有模板化功能的常规结构。 在这种情况下,编译器将为调用函数的每个类型生成一个operator()函数。它将从函数参数中推断出类型。