사용자 정의 std :: set 비교기 사용
정수 집합에서 항목의 기본 순서를 숫자 대신 사전 식으로 변경하려고하는데 다음을 g ++로 컴파일 할 수 없습니다.
file.cpp :
bool lex_compare(const int64_t &a, const int64_t &b)
{
stringstream s1,s2;
s1 << a;
s2 << b;
return s1.str() < s2.str();
}
void foo()
{
set<int64_t, lex_compare> s;
s.insert(1);
...
}
다음과 같은 오류가 발생합니다.
error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Compare, class _Alloc> class std::set’
error: expected a type, got ‘lex_compare’
내가 뭘 잘못하고 있죠?
펑터 (함수처럼 호출 될 수 있도록 () 연산자를 오버로드하는 클래스)를 사용해야하는 함수를 사용하고 있습니다.
struct lex_compare {
bool operator() (const int64_t& lhs, const int64_t& rhs) const {
stringstream s1, s2;
s1 << lhs;
s2 << rhs;
return s1.str() < s2.str();
}
};
그런 다음 클래스 이름을 유형 매개 변수로 사용합니다.
set<int64_t, lex_compare> s;
functor 상용구 코드를 피하려면 함수 포인터를 사용할 수도 있습니다 (함수라고 가정 lex_compare
).
set<int64_t, bool(*)(const int64_t& lhs, const int64_t& rhs)> s(&lex_compare);
1. 최신 C ++ 11 솔루션
auto cmp = [](int a, int b) { return ... };
std::set<int, decltype(cmp)> s(cmp);
우리는 사용 람다 기능을 비교한다. 평소와 같이 비교기는 첫 번째 인수로 전달 된 요소가 정의 된 특정 엄격한 약한 순서 에서 두 번째 인수보다 먼저 전달되는 것으로 간주되는지 여부를 나타내는 부울 값을 반환해야 합니다.
2. 첫 번째 솔루션과 유사하지만 람다 대신 함수가 있음
비교기를 일반적인 부울 함수로 만듭니다.
bool cmp(int a, int b) {
return ...;
}
그런 다음 사용
std::set<int, decltype(&cmp)> s(&cmp);
3. ()
연산자 와 함께 구조체를 사용하는 이전 솔루션
struct cmp {
bool operator() (int a, int b) const {
return ...
}
};
// ...
// later
std::set<int, cmp> s;
4. 대체 솔루션 : 부울 함수에서 구조체 생성
부울 함수 가져 오기
bool cmp(int a, int b) {
return ...;
}
그리고 그것을 사용하여 구조체를 만드십시오. std::integral_constant
#include <type_traits>
using Cmp = std::integral_constant<decltype(&cmp), &cmp>;
마지막으로 구조체를 비교기로 사용
std::set<X, Cmp> set;
Yacoby의 답변은 functor 상용구를 캡슐화하기위한 어댑터를 작성하도록 영감을줍니다.
template< class T, bool (*comp)( T const &, T const & ) >
class set_funcomp {
struct ftor {
bool operator()( T const &l, T const &r )
{ return comp( l, r ); }
};
public:
typedef std::set< T, ftor > t;
};
// usage
bool my_comparison( foo const &l, foo const &r );
set_funcomp< foo, my_comparison >::t boo; // just the way you want it!
와우, 그럴만 한 가치가 있다고 생각합니다!
다음과 같이 래핑하지 않고 함수 비교기를 사용할 수 있습니다.
bool comparator(const MyType &lhs, const MyType &rhs)
{
return [...];
}
std::set<MyType, bool(*)(const MyType&, const MyType&)> mySet(&comparator);
which is irritating to type out every time you need a set of that type, and can cause issues if you don't create all sets with the same comparator.
std::less<>
when using custom classes with operator<
If you are dealing with a set of your custom class that has operator<
defined, then you can just use std::less<>
, for example:
As mentioned at http://en.cppreference.com/w/cpp/container/set/find C++14 has added two new find
APIs:
template< class K > iterator find( const K& x );
template< class K > const_iterator find( const K& x ) const;
which allow you to do:
#include <cassert>
#include <set>
class Point {
public:
// Note that there is _no_ conversion constructor,
// everything is done at the template level without
// intermediate object creation.
//Point(int x) : x(x) {}
Point(int x, int y) : x(x), y(y) {}
int x;
int y;
};
bool operator<(const Point& c, int x) { return c.x < x; }
bool operator<(int x, const Point& c) { return x < c.x; }
bool operator<(const Point& c, const Point& d) {
return c.x < d;
}
int main() {
std::set<Point, std::less<>> s;
s.insert(Point(1, -1));
s.insert(Point(2, -2));
s.insert(Point(0, 0));
s.insert(Point(3, -3));
assert(s.find(0)->y == 0);
assert(s.find(1)->y == -1);
assert(s.find(2)->y == -2);
assert(s.find(3)->y == -3);
// Ignore 1234, find 1.
assert(s.find(Point(1, 1234))->y == -1);
}
Tested on Ubuntu 16.10, g++
6.2.0, with:
g++ -std=c++14 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
More info about std::less<>
can be found at: What are transparent comparators?
참고URL : https://stackoverflow.com/questions/2620862/using-custom-stdset-comparator
'development' 카테고리의 다른 글
blueimp 파일 업로드 플러그인의 maxFileSize 및 acceptFileTypes가 작동하지 않습니다. (0) | 2020.09.23 |
---|---|
이러한 파일을로드 할 수 없습니다 — sqlite3 / sqlite3_native (LoadError) on ruby on rails (0) | 2020.09.23 |
GridView가 양식 태그 내에 있더라도 runat =“server”인 양식 태그 내에 GridView를 배치해야합니다. (0) | 2020.09.23 |
명령에서 파일을 사용하고 출력을 자르지 않고 동일한 파일로 리디렉션하려면 어떻게해야합니까? (0) | 2020.09.23 |
SVN 사용자 이름 변경 (0) | 2020.09.23 |