2017-02-23 88 views
1

我有一个STL样列表容器定义了以下两个功能:错误模板函数被调用

// copy the specified VALUE some COUNT number of times and insert copies 
// right before POS. 
Iterator insert(Iterator pos, size_type count, const value_type 
      &value); 

// copy the values from [FIRST, LAST) from the specified Iterators and 
// place before POS. 
template<class InputIt> 
    Iterator insert(Iterator pos, InputIt first, InputIt last); 

然后我试着用一些任意的代码来测试我的功能实现:

std::list<int> stlList = { 1, 2, 3, 4, 5 }; 
MyList<int> intList; 

intList.insert(intList.begin(), 5, 0); // expected call to first insert 
intList.insert(intList.begin(), stlList.begin(), stlList.end()); // expected call to second insert 

但是,对于他们来说,这似乎是第二个函数被调用。我发现模糊不清,因为这两个函数都有三个参数,我看到编译器可能会调用错误的函数。但我不确定我错过了什么。我一直以STL为基础开发自己的功能,并且据我所知,他们以几乎相同的方式定义它们(STL's List Insert)。

+0

什么是'size_type'定义为? – NathanOliver

+0

我认为你的'size_type'是无符号的,所以模板方法是完全匹配的。你可以调用'intList.insert(intList.begin(),5u,0)' – Jarod42

+0

注意关于'std :: list :: insert'的重载(4)(带有两个迭代器的那个):“这个过载只有当InputIt符合InputIterator的条件时才会参与重载解析,以避免过载带来的不确定性(3)。“ –

回答

2

原因intList.insert(intList.begin(), 5, 0);的动产

template<class InputIt> 
Iterator insert(Iterator pos, InputIt first, InputIt last); 

Iterator insert(Iterator pos, size_type count, const value_type &value); 

是因为模板函数产生一个精确匹配。

50具有相同的类型,以便InputIt被推断为int这使得功能样子

Iterator insert(Iterator pos, int first, int last); 

如果你的另一超载看起来像

Iterator insert(Iterator pos, size_t first, int last); 

正如你可以看到没有转换需要调用模板推导的版本,所以它比非模板过载更受欢迎。

如果InputIt确实是一个迭代器,您必须将5转换为size_t以使其调用非模板过载或使用SFINAE仅调用模板过载。

2
template<class InputIt> 
    Iterator insert(Iterator pos, InputIt first, InputIt last); 

该模板定义了一个函数,其第二个和第三个参数是相同的类型。你在脑海中假设第二个和第三个参数必须是迭代器。但是这里没有这样的要求,只是第二个和第三个参数的类型必须相同。模板参数的名称“InputIt”是无关紧要的。

intList.insert(intList.begin(), 5, 0); // expected call to first insert 

第二和第三参数,以该函数调用是相同的类型:一个int。过载分辨率的另一个候选:

Iterator insert(Iterator pos, size_type count, const value_type 
     &value); 

这一个对第二个和第三个参数有不同的类型。虽然这两个ints都可以在这里转换,但另一个模板函数是更好的匹配,因此它被选中。