5

我正在通过加速 C++ 工作,并且遇到了 Ex 的问题。10.2 这些问题涉及重写前一章的中值函数,以便现在可以使用向量或内置数组调用中值。中值函数还应该允许任何算术类型的容器。

我无法对下面详述的中位数进行两次调用 - 我收到错误消息

No matching function for call to 'median'

我从一些研究中收集到,当使用模板时,应该在编译时知道类型。这可能是根本问题吗?有没有办法以某种方式将 Type 作为模板参数传递?

到目前为止,这是我的代码:

#include <iostream>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cstddef>

using namespace std;

template <class Iterator, class Type>
Type median(Iterator begin, Iterator end)
{
    vector<Type> vec(begin,end);
    typedef typename vector<Type>::size_type container_sz;
    container_sz size = vec.size();

    if (size == 0) {
        throw domain_error("median of an empty vector");
    }

    sort(vec.begin(), vec.end());

    container_sz mid = size/2;
    return size % 2 ==  0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];
}

int main()
{
    vector<int> grades;

    for (int i = 0; i != 10; ++i){
        grades.push_back(i);
    }

    const int int_array[] = {2, 9, 4, 6, 15};
    size_t array_size = sizeof(int_array)/sizeof(*int_array);

    cout << median(int_array, int_array + array_size) << endl;   //error here: Semantic Issue, No matching function for call to 'median' 
    cout << median(grades.begin(), grades.end()) << endl;        //error here: Semantic Issue, No matching function for call to 'median' "

    return 0;
}
4

2 回答 2

4

通常,解决此问题的最佳方法是iterator_traits如上所述使用。然而,为了回答书中的特定问题 10.2(不假定Iterator_trait知识),可以进行如下操作: - 注意必须首先列出类 Type,而不是类 Iterator。此外,一个必须调用median<int>(grades.begin(), grades.end())而不是median(grades.begin(), grades.end())

#include <iostream>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cstddef>

using namespace std;

template <class Type, class Iterator>       //the order allows the second template parameter type to be deduced (Iterator)                                           
Type median(Iterator begin, Iterator end)   //while requiring you still provide the first type
{

    vector<Type> vec(begin,end);

    //typedef typename vector<Type>::size_type container_sz;
    //container_sz size = vec.size()
    auto size = vec.size();

    if (size == 0) {
        throw domain_error("median of an empty vector");
    }

    sort(vec.begin(), vec.end());

    //container_sz mid = size/2
    auto mid = size/2;

    Type ret = size % 2 ==  0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];

    return ret;
}


int main()
{

    vector<int> grades = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    const int int_array[] = {2, 9, 4, 6, 15};

    size_t array_size = sizeof(int_array)/sizeof(*int_array);

    cout << median<int>(int_array, int_array + array_size) << endl;  //must provide int here, in order to give the template the return type at compile time
    cout << median<int>(grades.begin(), grades.end()) << endl;


return 0;

}

于 2013-05-15T20:13:57.483 回答
3

您的错误源于Type提供的参数无法推断出。您可以使用标准库类执行此操作iterator_traits,如下所示:

template <
    class Iterator, 
    class Type = typename std::iterator_traits<Iterator>::value_type>
Type median(Iterator begin, Iterator end)
{
    vector<Type> vec(begin,end);

    typedef typename vector<Type>::size_type container_sz;

    container_sz size = vec.size();

    if (size == 0) {
        throw domain_error("median of an empty vector");
    }

    sort(vec.begin(), vec.end());

    container_sz mid = size/2;

    return size % 2 ==  0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];
}

该类iterator_traits剖析了提供的 Iterator 类型以确定它实际迭代的内容(比这更复杂一点,但这是一个不错的总结)。有关其工作原理的更多信息,请参阅class iterator_traits. 它是确定迭代器值类型的最方便的机制。

注意:为确保不会意外绕过默认模板参数Type声明,您还可以执行以下操作:

template <class Iterator>
typename std::iterator_traits<Iterator>::value_type median(Iterator begin, Iterator end)
{
    if (begin == end)
        throw domain_error("median of an empty vector");

    typedef typename std::iterator_traits<Iterator>::value_type Type;
    std::vector<Type> vec(begin,end);
    sort(vec.begin(), vec.end());

    typename std::vector<Type>::size_type mid = vec.size()/2;
    return vec.size() % 2 ==  0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];
}

它有点密集,并且丢掉了大部分中间的东西,但是如果你盯着它看足够长的时间,你就会明白它是如何工作的,它会减少你的模板参数列表,只使用你真正关心的一个东西;类型,由Iterator您提供给函数的参数简单推断。

于 2013-05-15T18:43:17.430 回答