C ++ジェネリック

ジェネリック

魯迅

様々な機能におけるアルゴリズムのC ++標準ライブラリには、強力な適用性を持っています。一例のためのstd::sort機能、すなわち、それはできstd::vector素子の一種であり、することが可能であるstd::deque配列の要素のために、それはまた、正常に動作することができ、要素を並べ替えます。一方、std::sort関数はまた、照合を指定するための関数ポインタ(述部)を受け入れることができます。この記事では、標準ライブラリのシミュレートされますstd::sort、機能をその同じインタフェースのソート関数を書きます。

ここではマージソート方法をされて仕分け、主なアイデアは、長い方ソート順にソート2の短い配列にあります。一般に、配列は、二つの短いシーケンスがソート機能をマージ必要とする、無秩序です。シーケンスは一つだけの要素であるならば、それは、再帰端を注文する必要があります。図は、可動は、以下を示し:(可動図をインターネットから)

以下を参照してくださいstd::sortインターフェイス機能。std::sort関数は、返却値をもたない(又は戻りvoid、開始位置とデフォルトシーケンスの末尾位置、ならびに照合を指定するオプションのパラメータを示す2回の反復子の受信機)<比較のために。

だから我々は、ソート機能インタフェースのように長くなることがあります。

template<typename RandIter>
void merge_sort
(
    RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
    TYPE comp = ...//排序规则
)

どこの説明を次のコードの最初の行RandIterのような適切な型に関数呼び出しを置き換えますクラス名、int*std::vector<int>::iteratorなどが挙げられます。compバイナリ述語されると、RandIter決定され、comp型がそれに沿って決定されます。そのようなRandIterことはstd::deque<int>::iterator、コアメンバーがデータであるintタイプ、述語であるbool (*comp) (int a, int b)、すなわち、二つの収容int変数を返すbool関数型へのポインタ。しかし、異なるイテレータ型のさまざまな、どのようにするかを決定するにはTYPE

標準ライブラリ・イテレータクラス注文容器の様々な、パッケージ有するvalue_type配列内の要素を指すの種類を説明するために、このような二重の記憶素子としてstd::vectorイテレータであるvalue_typeことstd::vector<double>::iterator::value_typeファクトdoubleタイプ。したがって、compタイプがTYPE書き込むことができますtypename RandIter::value_type

しかし、通常の配列のために、2回の反復子がポインタで渡されたが、ないポインタ型value_typeの!だから、言葉は配列を扱うことができない書き込み。

最初の文書ではtype_traits、標準ライブラリは、型変換機能の多くを提供します。タイプに対してint*、どの基準溶液の種類intより一般的なタイプのためにT、場合同じタイプ、それを使用することができる型を得ることU*Ttype_traitsstd::remove_pointer<T>::typeU

同じことはromove_pointer、ポインタを操作し、コンテナの順序のために何もできません。

C ++も提供しautodecltypeキーが推論を入力します。インタフェースの機能は、使用することはできませんautoで。そこで、我々は落ちる願っていますdecltype上。

必要なのは、ある*iterBegタイプが、decltype間接参照は、参照型となりますので、我々はまだ標準ライブラリのヘッダファイルのヘルプが必要なtype_traitsの一つremove_reference、自然への参照を削除する機能を。次のようにこのように、インターフェース機能です。

template<typename RandIter>
void merge_sort
(
    RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
    bool (*comp)(typename std::remove_reference<decltype(*iterBeg)>::type, typename std::remove_reference<decltype(*iterBeg)>::type) = ...//排序规则
)

タイプ名が解決され、以下のデフォルトのパラメータです。ここでは、ラムダ式を渡しますcomp

bool (*comp)(...) = [](typename std::remove_reference<decltype(*iterBeg)>::type a, typename std::remove_reference<decltype(*iterBeg)>::type b){return a < b;}

私は、全体のインターフェースがこれです書き出します:

template<typename RandIter>
void merge_sort
(
    RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
    bool (*comp)(typename std::remove_reference<decltype(*iterBeg)>::type, 
        typename std::remove_reference<decltype(*iterBeg)>::type) = []
        (typename std::remove_reference<decltype(*iterBeg)>::type a,
         typename std::remove_reference<decltype(*iterBeg)>::type b) ->bool
            {return a < b; }    
)

参照が行われたとき、私は達成するために、デフォルトパラメータの代わりにヘビーデューティーを使用してそれを見つけ、Visual Studioのバージョンの採用を実装するために、前にこの機能を書いて、そのインターフェースは、クールなたくさんのことのようです。

template<typename RandIter>
void merge_sort//这里使用 '<' 来排序
(
    RandIter iterBeg, RandIter iterEnd //开始与尾后迭代器
);

template<typename RandIter, typename Pred>
void merge_sort//这里使用 comp 来排序
(
    RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
    Pred comp//排序规则
);

ここでは、スキップすることができ、テーマ、とはほとんどの機能の一部が、あります。

template<typename RandIter>
void merge_sort
(
    RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
    bool (*comp)(typename std::remove_reference<decltype(*iterBeg)>::type, 
        typename std::remove_reference<decltype(*iterBeg)>::type) = []
        (typename std::remove_reference<decltype(*iterBeg)>::type a,
         typename std::remove_reference<decltype(*iterBeg)>::type b) ->bool
            {return a < b; }    
)
{
    //递归终止条件为子序列只有一个元素,一个元素一定是有序的
    //第二个判断条件是为了防止输入空序列
    if (iterBeg + 1 == iterEnd || iterBeg == iterEnd)
        return;

    RandIter iterMid = iterBeg + (iterEnd - iterBeg) / 2;//指向序列中间位置
    merge_sort(iterBeg, iterMid, comp);//递归
    merge_sort(iterMid, iterEnd, comp);//只有子序列有序才进行合并
    std::vector<std::remove_reference<decltype(*iterBeg)>::type>temp;//用来存储合并的有序序列
    temp.reserve(iterEnd - iterBeg);//保留空间用于存诸元素,防止空间扩张带来的额外花销
    auto it1 = iterBeg, it2 = iterMid;//分别指向两个子序列的开始位置
    while (it1 != iterMid || it2 != iterEnd)//还有元素没处理
    {
        if (it1 == iterMid)//序列1的元素已放完
            temp.emplace_back(*it2++);//只能放序列2的元素,后加的优先级高于解引用 (解引用与前加同级)
        else if (it2 == iterEnd)
            temp.emplace_back(*it1++);
        else
            temp.emplace_back(comp(*it1, *it2) ? *it1++ : *it2++);//按谓词规定的顺序放入
    }

    //将排好序的序列复制到原序列中的位置
    typename std::vector<std::remove_reference<decltype(*iterBeg)>::type>::iterator itTemp = temp.begin();//第一个typename说明iterator是一个类型名
    for (RandIter it2 = iterBeg; it2 != iterEnd; ++itTemp, ++it2)
        * it2 = *itTemp;
}

その場には、本明細書中で使用される、ソート操作をマージすることはできませんvector一時的なデータを格納します。

完成

おすすめ

転載: www.cnblogs.com/xunxunxun/p/11440531.html