我正在完成“加速 C++”中的练习,并且发现了一些我不理解的关于编译器如何推断函数模板中的类型的行为。在练习 10-2 中,我们被要求编写一个模板函数,它可以计算 vector 或内置数组中算术类型列表的中位数。我偶然发现了这个问题的示例解决方案,其中涉及一个模板函数,该函数计算并返回两个迭代器之间的中值容器值,即我创建了以下名为“median.hpp”的文件:
#ifndef median_hpp
#define median_hpp
#include <algorithm>
#include <stdexcept>
#include <vector>
using std::domain_error;
using std::sort;
using std::vector;
template <class T, class Iterator>
T median(Iterator begin, Iterator end) {
//check if the container is empty
if (begin == end)
throw domain_error("median of an empty container");
//create a vector with the same type as the container
//and copy the container contents into it
vector<T> temp;
for ( ; begin != end; ++begin)
temp.push_back(*begin);
//sort the temporary vector, and compute and return the median
sort(temp.begin(), temp.end());
size_t mid = temp.size() / 2;
T ret = (temp.size() % 2 == 0)
? (temp[mid] + temp[mid - 1]) / 2
: temp[mid];
return ret;
}
#endif /* median_hpp */
因此,如果我想计算数组和 vector 的中值,以证明该函数适用于两种容器类型,我将使用上述模板函数,如下所示:
#include <iostream>
#include <vector>
#include "median.hpp"
using std::vector;
using std::cout;
using std::cin;
using std::endl;
int main()
{
int arr[] = {12,2,4,1,4,56,1};
const size_t nData = sizeof(arr)/sizeof(*arr);
vector<double> v(arr, arr + nData);
cout << median(v.begin(),v.end()) << endl;
cout << median(arr, arr + nData) << endl;
return 0;
}
但是,由于我不明白的原因,我收到以下错误:
没有调用“中位数”的匹配函数...候选模板被忽略:无法推断模板参数“T”
据我所知,问题在于编译器无法从取消引用的迭代器中推断出“T”的类型。我想知道
A.为什么会发生这种情况?
B.有没有优雅的方法来解决这个问题?
最佳答案
编译器可以推断出Iterator
,但不能推断出T
。这是因为操作者无法说明如何从您传递给它的任何内容中推断出 T
。 迭代器
?从未知的 Iterator
类型,您如何在不知道 Iterator
实际是什么的情况下知道 T
是什么?编译器根本不知道这一点。
但是,由于您知道 Iterator
是实际的迭代器类型,并且大多数迭代器都具有返回到所包含类型 T
的类型别名,因此您可以执行类似的操作
template <class Iterator, class T = typename std::iterator_traits<Iterator>::value_type>
T median(Iterator begin, Iterator end) { ... }
有关所有这些的信息可以从例如收集this std::vector
reference它告诉您 vector 中的迭代器类型是 random access iterator其中提到了 value_type
以及如何从 std::iterator_traits
找到它.
std::iterator_traits
应该可以用于所有标准迭代器,而不仅仅是 std::vector 给出的随机访问迭代器。
关于c++ - 从模板函数中取消引用的迭代器推断类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37241120/