10

使用する利点は何boost::any_rangeですか?次に例を示します。

typedef boost::any_range<
    int
  , boost::forward_traversal_tag
  , int
  , std::ptrdiff_t
> integer_range;

void display_integers(const integer_range& rng)
{
    boost::copy(rng,
                std::ostream_iterator<int>(std::cout, ","));

    std::cout << std::endl;
}

int main(){
    std::vector<int> input{ ... };
    std::list<int> input2{ ... };
    display_integers(input);
    display_integers(input2);
}

ただし、ForwardRangeの概念を満たすテンプレートパラメータを使用すると、より効率的な同じ機能を実現できます。

template <class ForwardRange>
void display_integers(const ForwardRange& rng)
{
    boost::copy(rng,
                std::ostream_iterator<int>(std::cout, ","));

    std::cout << std::endl;
}

したがって、any_rangeを使用する価値があるシナリオを探しています。多分私は何かが欠けています。

4

2 に答える 2

17

この手法は型消去と呼ばれます。次の例の長所と短所を説明する完全な記事がありますany_iteratorC++でのオブジェクト指向プログラミングとジェネリックプログラミングの間の緊張について。

(別のファイル/ライブラリで)の実装/定義を隠すことが可能です

void display_integers(const integer_range& rng)

しかしの場合

template <class ForwardRange>
void display_integers(const ForwardRange& rng)

ユーザーにソースコードを提供する必要があります(または少なくともどこかで明示的なインスタンス化を行う必要があります)。

さらに、最初のケースでは、は1display_integers回だけコンパイルされますが、2番目のケースでは、渡された範囲のすべてのタイプに対してコンパイルされます。

また、あなたはどこかにあるかもしれません

integer_range rng;

そして、あなたの生涯の間に、それに異なるタイプrngの範囲を割り当てることができます:

vector<int> v;
list<int> l;
integer_range rng;
rng = v;
rng = l;

型消去の最大の欠点は、実行時のコストです。すべての操作は仮想であり、インライン化することはできません(簡単に)。


PS型消去のもう1つの有名な例は、std::functionです。

于 2013-03-15T21:34:30.260 に答える
10

boost::any_range関数から範囲を返すために使用できます。次の例を想像してみてください。

auto make_range(std::vector<int> v) -> decltype(???)
{   
    return v | filter([](int x){ return x % 2 == 0;})
        | transform([](int x){ return x * 2;});
}

*:gccは上記をラップせずにコンパイルしませんstd::function。howerclang3.2はラムダを直接渡すことで機能します

この関数から何が返されるかを知ることは非常に困難です。また、ラムダとdecltypeは一緒に機能しないためdecltype、ラムダのみを渡すときにを使用して型を推測することはできません。1つの解決策はboost::any_range、例のように使用することです(別の回避策は、コメントでEvgeny Panasyukstd::functionが指摘したように使用することです):

integer_range make_range(std::vector<int> v)
{
     return v | filter([](int x){ return x % 2 == 0;})
        | transform([](int x){ return x * 2;});
}

を使用したgccでの作業例std::function

clangがラムダを直接渡す作業例。

于 2013-03-15T21:42:47.127 に答える