std :: set에 대한 std :: back_inserter?


96

이것은 간단한 질문이라고 생각합니다. 다음과 같이해야합니다.

std::set<int> s1, s2;
s1 = getAnExcitingSet();
std::transform(s1.begin(), s1.end(), std::back_inserter(s2), ExcitingUnaryFunctor());

물론, std::back_inserter어떤이 이후 작업은하지하지 않습니다 push_back. std::inserter반복자가 필요합니까? 사용 std::inserter하지 않아서 어떻게해야할지 모르겠습니다.

누구 아이디어가 있습니까?


물론 내 다른 옵션은에 벡터를 사용한 s2다음 나중에 정렬하는 것입니다. 그게 더 좋을까요?

답변:


141

setpush_back요소의 위치는 세트의 비교기에 의해 결정되기 때문에 없습니다 . std::inserter그것을 사용 하고 전달하십시오 .begin():

std::set<int> s1, s2;
s1 = getAnExcitingSet();
transform(s1.begin(), s1.end(), 
          std::inserter(s2, s2.begin()), ExcitingUnaryFunctor());

그런 다음 삽입 반복기는 기록 될 때 반복기에 전달 된 값이 s2.insert(s2.begin(), x)어디에 있는지 호출 x합니다. 이 세트는 삽입 할 위치 힌트로 반복기를 사용합니다. 당신은 잘 사용할 수 있습니다 s2.end().


2
inserter(vec, vec.end())벡터에서도 작동하기 때문에 왜 처음부터 back_inserter를 사용합니까?
NHDaly 2010 년

7
@NHDaly : back_inserter가 더 빠르기 때문에
marton78 2014

@ marton78하지만 아주 작은 마진으로 만 더 빨라야하지 않나요? 요소를 이동할 필요가 없을 때 벡터 insert대신 호출 push_back은 거의 동일해야합니다 (O (1)).
Felix Dombek

3
@FelixDombek 당신이 맞습니다, 그것은 많이 느리지 않을 것입니다. v.insert(x, v.end())시작 부분에 추가 분기가 있습니다 (n 개의 요소를 이동하기 때문에 여기서 n은 0입니다). 그러나 inserter1)을 사용하는 것은 push_back2)를 사용하는 것과는 다른 의도를 전달하며 독자가 멈춰서 3)을 비관적으로 생각하게 만듭니다.
marton78

0

2016 년에는 "단일 인수 inserter반복자"를 제안했습니다 . https://isocpp.org/files/papers/p0471r0.html . 제안이 진행되었는지 알 수 없었습니다. 말이되는 것 같아요.

지금은 maker 함수를 정의하는이 동작을 가질 수 있습니다.

template<class Container>
auto sinserter(Container& c){
    using std::end;
    return std::inserter(c, end(c));
}

다음으로 사용 :

std::transform(begin(my_vec), end(my_vec), sinserter(my_set), [](auto& e){return e.member;});

이것은 모든 표준 컨테이너에서 작동하도록 의도 되었습니까? std :: forward_list에서는 작동하지 않습니다 (컴파일러 오류는 "forward_list에의 인스턴스화 내부에 '삽입'이라는 이름의 멤버가 없습니다"입니다 insert_iterator::operator=). 그럴까요?
Don Hatch

@DonHatch, insert(및 end) 이있는 모든 것 . 처음 forward_list에는 insert작업 이없는 것 같습니다 insert_after. 그리고 그것이 변경 되어도 마지막 후에는 삽입 할 수 없다고 생각합니다. std::list대신 사용할 수 없습니까 ?
alfC

물론 저는 개인적으로 std :: forward_list가 필요하지 않습니다. 그러나 나는 일반적인 "한 컨테이너를 다른 컨테이너로 어떻게 복사합니까?"에 관심이 있습니다. 의미가있는 모든 컨테이너 쌍에 대해. 내 현재 관심은 @HowardHinnant의 short_alloc과 같은 일반 컨테이너 할당자를 실행하는 것입니다.
Don Hatch

@DonHatch, 문제는 그 질문에 많은 변형이 있다는 것입니다. ( ""어떻게 한 컨테이너를 다른 컨테이너에 복사합니까? "). 예를 들어 원래 값을 보존하고 싶습니까, 할당을 최소화하고 싶습니까? 가장 간단한 경우 제 생각에 가장 좋은 대답은 다음을 사용하는 것입니다. 두 개의 반복자를 취하는 컨테이너를 생성합니다 (대부분의 컨테이너는 그것을 취할 수 있습니다) NewContaner new_container(old_other_container.begin(), old_other_container.end()).
alfC

1
예, std :: set은 SequentialContainer가 아니며 괜찮습니다. :-) existing_list = std::list(c.begin(), c.end(), existing_list.get_allocator()) 아주 좋습니다. 제 대답이라고 생각합니다. 건배!
Don Hatch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.