2017-03-29 3 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를 포함한다면, 오직 하나의 2가 c에 존재할 것이다.

a) C++ 11에서이 코드를 어떻게 적용 할 수 있습니까? 더 적은 <> 및 마이너스 <> 매개 변수가 될 수있는 직관적 인 도약은 ......... difference_type이 작동하지 않아 컴파일러 메시지가 도움이되지 않습니다.

b) 현재 버전은 시퀀스 일치를 마지막으로 제거합니다. 어떤 코드가 먼저 제거 일치합니까?

+4

오 와우,'표준 : bind'합니다. 그것을 사용하지 마십시오 (C++ 11 및 C++ 14 모두) – Ap31

+1

대신 람다를 사용하십시오. 그러나 알고리즘을 다시 생각할 필요가 있다고 말하고 싶습니다. – Ap31

+0

@ Ap31 이론적 인 질문에 대한 그런 종류의 논평 . 오, 나는 거기에 개념이 있다는 것을 알고있다. 이제는 람다가 있기 때문에 바인딩이 필요 없다. 그러나 실제로 람다와 바인드는 C++ 11보다 먼저 나오지 만 함께 표준에 들어갔고 후자는 존재하지 않았다. 질문은 리팩토링 코드가 아니었다. – Swift

답변

7

진짜 대답은 bind()을 사용하지 않는 것입니다. 람다를 사용 :이, C++ 11에서 작동하고, 이해하기 훨씬 쉽게 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); 
}); 

. 그리고 우리는 수동 템플릿 공제도 필요가 없습니다.

우리는 또한이 방법으로 작성한 수

: 지금 참조 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); 
}); 

참고. 또한 제안 된 확장 기능을 구현하여 첫 번째 일치 항목을 제거하는 방법을 더 쉽게 알 수 있습니다. 그건 그냥 우리가 비교하는 a에있는 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]'인가? [data] (http://en.cppreference.com/w/cpp/container/vector/data)에 문제가 있습니까? – Yakk

+0

@Yakk 다른 버전과 더 짧고 대칭입니다. – Barry

+0

아직 내 문제는 적어도 하나의 upmost 바인딩 및 lcc (분산 된 sparc 컴파일러) 및 vc 2010 컴파일러와 호환되는 완전히 도울 수 없다는 것입니다 () 완전히 C++ 11 컴파일러와 함께 작동하지 않습니다 , 적은 <>를 대체 할 수있는 사소한 구현은 작동하지 않습니다 – Swift