2017-03-29 35 views
2

へのポーティングコード以下は、カウントとの値が一致するものを除く。ベクトルaの要素からベクトルcを作成するためのものですテンプレート控除:C++ 11

// g++ -std=c++14 -pedantic -pthread main.cpp 
// output: 1 2 3 4 5 1 1 1 
#include <algorithm> 
#include <vector> 
#include <functional> 
#include <iterator> 
#include <iostream> 

int main() 
{ 
    std::vector<int> a = { 1, 2, 3, 2, 4, 5, 1, 1, 3, 5, 1, 5 }, b = { 2, 5, 5, 3 }, c; 

    std::copy_if(a.begin(), a.end(), std::back_inserter(c), 
    std::bind(std::less<>(), // this won't work in pre-C++14 
     std::bind(
     std::count<std::vector<int>::iterator, int>, 
      std::bind(static_cast<std::vector<int>::iterator (std::vector<int>::*)()>(&std::vector<int>::begin), &c), 
      std::bind(static_cast<std::vector<int>::iterator (std::vector<int>::*)()>(&std::vector<int>::end), &c), 
      std::placeholders::_1 
    ), 
     std::bind(
     std::minus<>(), // this won't work in pre-C++14 
      std::bind(
      std::count<std::vector<int>::iterator, int>, 
       a.begin(), 
       a.end(), 
       std::placeholders::_1 
     ), 
      std::bind(
      std::count<std::vector<int>::iterator, int>, 
       b.begin(), 
       b.end(), 
       std::placeholders::_1 
     ) 
    ) 
    ) 
); 

    std::copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, " ")); 
    std::cout << std::endl; 
} 

C++ 14コンパイラのための法的ですベクトルbの要素。例えば。 aが3つの2つとb - 2つを含む場合、cには1つの2つしか存在しません。

a)このコードをC++ 11にどのように適合させることができますか?コンパクトメッセージは役に立ちません。

b)現在のバージョンでは、最後の一致がシーケンスごとに削除されます。どのようなコードが最初にと一致しますか?

+4

をすごいああ、 'のstd :: bind':それはちょうど私達が比較しているa内のどのelemの側に変化です。それを使用しないでください(C++ 11とC++ 14の両方で) – Ap31

+1

の代わりにラムダを使用しますが、あなたのアルゴリズムも再考する必要があると言います。 – Ap31

+0

@ Ap31そのような理論的な質問。ああ、私は概念があることを知っています:ラムダがありますので、バインドする必要はありません。しかし、実際にはラムダとバインドはC++ 11より前ですが、一緒に標準に入り、後者は存在しませんでした。質問はリファクタリングコードではない – Swift

答えて

7

本当の答えはちょうどbind()を使用しないことです。ラムダを使用します。これは、std::bind()とのソリューションよりもはるかに短い

std::copy_if(a.begin(), a.end(), std::back_inserter(c), [&](int elem){ 
    return std::count(c.begin(), c.end(), elem) < 
     std::count(a.begin(), a.end(), elem) - std::count(b.begin(), b.end(), elem); 
}); 

を、C++ 11で動作し、理解しやすいはるかです。また、手動テンプレート控除の必要もありません。

我々はまた、それをこのように書かれている可能性が:私は今、参照によってelemを取っている

std::copy_if(a.begin(), a.end(), std::back_inserter(c), [&](int& elem){ 
    return std::count(&elem + 1, &a[a.size()], elem) >= 
     std::count(b.begin(), b.end(), elem); 
}); 

注意。これにより、提案された拡張機能を実装して最初のマッチを削除する方がもっと簡単になります。

std::copy_if(a.begin(), a.end(), std::back_inserter(c), [&](int& elem) { 
    return std::count(&a[0], &elem, elem) >= 
     std::count(b.begin(), b.end(), elem); 
}); 
+0

なぜ '&a [0]'ですか? [データ](http://en.cppreference.com/w/cpp/container/vector/data)に問題がありますか? – Yakk

+0

@Yakk他のバージョンとより短く、より対称です。 – Barry

+0

まだ私の問題は、少なくとも1つの最上位のバインドとlcc(分散型sparcコンパイラ)とvc 2010コンパイラとの互換性は完全にC++ 11コンパイラで動作するlesser ()を受け入れないことです、より少ない<>に取って代わる簡単な実装は実現しない – Swift

関連する問題