5

私はアクセラレートされた C++ を使用していますが、Ex で問題が発生しました。10.2 質問には、前の章の median 関数を書き換えて、ベクトルまたは組み込み配列で median を呼び出すことができるようにすることが含まれます。median 関数は、任意の算術型のコンテナーも許可する必要があります。

以下で説明する中央値への 2 つの呼び出しを行うことができません - エラー メッセージが表示されます

No matching function for call to 'median'

テンプレートを使用する場合、コンパイル時に Type を認識しておく必要があるという調査結果がいくつかあります。これが根本的な問題ではないでしょうか?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

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 に答える