수락 된 답변 의 첫 번째 (잘 투표 된) 의견은 기존 표준 집합 작업에 대한 누락 된 연산자에 대해 불평합니다.
한편으로는 표준 라이브러리에 그러한 연산자가 없다는 것을 이해합니다. 다른 한편으로, 원하는 경우 (개인의 기쁨을 위해) 쉽게 추가 할 수 있습니다. 나는 과부하
operator *()
세트의 교차
operator +()
세트의 결합을 위해.
샘플 test-set-ops.cc
:
#include <algorithm>
#include <iterator>
#include <set>
template <class T, class CMP = std::less<T>, class ALLOC = std::allocator<T> >
std::set<T, CMP, ALLOC> operator * (
const std::set<T, CMP, ALLOC> &s1, const std::set<T, CMP, ALLOC> &s2)
{
std::set<T, CMP, ALLOC> s;
std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
std::inserter(s, s.begin()));
return s;
}
template <class T, class CMP = std::less<T>, class ALLOC = std::allocator<T> >
std::set<T, CMP, ALLOC> operator + (
const std::set<T, CMP, ALLOC> &s1, const std::set<T, CMP, ALLOC> &s2)
{
std::set<T, CMP, ALLOC> s;
std::set_union(s1.begin(), s1.end(), s2.begin(), s2.end(),
std::inserter(s, s.begin()));
return s;
}
#include <iostream>
using namespace std;
template <class T>
ostream& operator << (ostream &out, const set<T> &values)
{
const char *sep = " ";
for (const T &value : values) {
out << sep << value; sep = ", ";
}
return out;
}
int main()
{
set<int> s1 { 1, 2, 3, 4 };
cout << "s1: {" << s1 << " }" << endl;
set<int> s2 { 0, 1, 3, 6 };
cout << "s2: {" << s2 << " }" << endl;
cout << "I: {" << s1 * s2 << " }" << endl;
cout << "U: {" << s1 + s2 << " }" << endl;
return 0;
}
컴파일 및 테스트 :
$ g++ -std=c++11 -o test-set-ops test-set-ops.cc
$ ./test-set-ops
s1: { 1, 2, 3, 4 }
s2: { 0, 1, 3, 6 }
I: { 1, 3 }
U: { 0, 1, 2, 3, 4, 6 }
$
내가 싫어하는 것은 연산자의 반환 값 복사본입니다. 아마도 이것은 이동 할당을 사용하여 해결할 수 있지만 여전히 내 기술을 넘어서는 것입니다.
이러한 "새로운 멋진"이동 의미 체계에 대한 제한된 지식으로 인해 반환 된 집합의 복사본을 유발할 수있는 연산자 반환에 대해 걱정했습니다. Olaf Dietschestd::set
는 이미 이동 생성자 / 할당을 갖추고 있으므로 이러한 문제가 불필요 하다고 지적했습니다 .
나는 그를 믿었지만 이것을 어떻게 확인할지 생각하고 있었다. 사실 아주 쉽습니다. 템플릿은 소스 코드로 제공되어야하므로 디버거를 사용하면됩니다. 따라서, 나는 오른쪽에 브레이크 포인트를 배치 return s;
의 operator *()
과에 즉시 나를 납을 첨가 한 단계로 진행 std::set::set(_myt&& _Right)
: 등함으로써 해결할 - 이동 생성자입니다. (나의) 깨달음을 주셔서 감사합니다, 올라프.
완전성을 위해 해당 할당 연산자도 구현했습니다.
operator *=()
세트의 "파괴적인"교차점
operator +=()
세트의 "파괴적인"결합을 위해.
샘플 test-set-assign-ops.cc
:
#include <iterator>
#include <set>
template <class T, class CMP = std::less<T>, class ALLOC = std::allocator<T> >
std::set<T, CMP, ALLOC>& operator *= (
std::set<T, CMP, ALLOC> &s1, const std::set<T, CMP, ALLOC> &s2)
{
auto iter1 = s1.begin();
for (auto iter2 = s2.begin(); iter1 != s1.end() && iter2 != s2.end();) {
if (*iter1 < *iter2) iter1 = s1.erase(iter1);
else {
if (!(*iter2 < *iter1)) ++iter1;
++iter2;
}
}
while (iter1 != s1.end()) iter1 = s1.erase(iter1);
return s1;
}
template <class T, class CMP = std::less<T>, class ALLOC = std::allocator<T> >
std::set<T, CMP, ALLOC>& operator += (
std::set<T, CMP, ALLOC> &s1, const std::set<T, CMP, ALLOC> &s2)
{
s1.insert(s2.begin(), s2.end());
return s1;
}
#include <iostream>
using namespace std;
template <class T>
ostream& operator << (ostream &out, const set<T> &values)
{
const char *sep = " ";
for (const T &value : values) {
out << sep << value; sep = ", ";
}
return out;
}
int main()
{
set<int> s1 { 1, 2, 3, 4 };
cout << "s1: {" << s1 << " }" << endl;
set<int> s2 { 0, 1, 3, 6 };
cout << "s2: {" << s2 << " }" << endl;
set<int> s1I = s1;
s1I *= s2;
cout << "s1I: {" << s1I << " }" << endl;
set<int> s2I = s2;
s2I *= s1;
cout << "s2I: {" << s2I << " }" << endl;
set<int> s1U = s1;
s1U += s2;
cout << "s1U: {" << s1U << " }" << endl;
set<int> s2U = s2;
s2U += s1;
cout << "s2U: {" << s2U << " }" << endl;
return 0;
}
컴파일 및 테스트 :
$ g++ -std=c++11 -o test-set-assign-ops test-set-assign-ops.cc
$ ./test-set-assign-ops
s1: { 1, 2, 3, 4 }
s2: { 0, 1, 3, 6 }
s1I: { 1, 3 }
s2I: { 1, 3 }
s1U: { 0, 1, 2, 3, 4, 6 }
s2U: { 0, 1, 2, 3, 4, 6 }
$