algorithm의 sort 메서드에 대한 질문입니다.

  • sooshia
    sooshia

    (탑코더 srm166 div1 250번 문제를 풀다가 질문합니다.)
    클래스 안에서 algorithm의 sort 메서드를 이용하는데 사용자 정의 비교함수를 만들어서 하려고 합니다. 아래와 같이 만들면 잘 동작 합니다.
    그런데 사용자 정의 비교를 꼭 binary_function을 상속받은 구조체를 만들어서 구현해야만 하는건가요?
    class BinaryCardinality {
    public:
    struct comp : public binary_function {
    int count(int x) {
    int count(0), i(1);
    while (i return count;
    }
    bool operator()(int x, int y) {
    if (count(x)==count(y)) return x else return count(x) }
    };
    vector arrange(vector numbers) {
    // begin
    sort(numbers.begin(), numbers.end(), comp());
    return numbers;
    // end

    }
    };
    예를들어
    int count(int x) {
    int count(0), i(1);
    while (i return count;
    }
    inline bool comp(int x, int y) {
    if (count(x)==count(y)) return x else return count(x) }
    class BinaryCardinality {
    public:
    vector arrange(vector numbers) {
    // begin
    sort(numbers.begin(), numbers.end(), comp);
    return numbers;
    // end

    }
    };
    이렇게 클래스 밖으로 비교에 관련된 함수를 빼주면 잘 동작하는데
    class BinaryCardinality {
    private:
    int count(int x) {
    int count(0), i(1);
    while (i return count;
    }
    inline bool comp(int x, int y) {
    if (count(x)==count(y)) return x else return count(x) }
    public:
    vector arrange(vector numbers) {
    // begin
    sort(numbers.begin(), numbers.end(), BinaryCardinality::comp);
    return numbers;
    // end

    }
    };
    이런식으로 포함하고 있으면 컴파일 에러가 발생합니다.
    마지막 방식으로 구현하려면 어떻게 해야하는지 아시는분 답변 부탁드립니다.

    [이 글은 과거 홈페이지에서 이전된 글입니다. 원문보기]


    16년 전
10개의 댓글이 있습니다.
  • 바아보오
    바아보오

    sort()는 전역으로 사용되는데, comp는 private로 선언되어서 그런것 같은데요...


    16년 전 link
  • MiNu
    MiNu

    comp를 static bool comp로 정의해보세요;;


    16년 전 link
  • sooshia
    sooshia

    comp와 count 함수를 모두 static 으로 만들어주니 동작합니다.
    어짜피 내부에서 사용되는 함수이기 때문에 static이 아니어도 동작할 것이라 생각했는데
    이유가 무엇일까요?
    (답변 감사합니다 ^^)
    최종소스는
    class BinaryCardinality {
    private:
    static inline int count(int x) {
    int count(0), i(1);
    while (i return count;
    }
    static inline bool comp(int x, int y) {
    if (count(x)==count(y)) return x else return count(x) }
    public:
    vector arrange(vector numbers) {
    // begin
    sort(numbers.begin(), numbers.end(), comp);
    return numbers;
    // end

    }
    };
    이렇습니다.


    16년 전 link
  • sooshia
    sooshia

    엑세스 관련 에러가 발생하진 않아서 그쪽 문제는 아닌 것 같습니다.
    답변 고맙습니다. ^^


    16년 전 link
  • sooshia
    sooshia

    참고로.. comp앞에 static이 빠지면
    topcoder.cpp: In member function ‘std::vector > BinaryCardinality::arrange(std::vector >)’:
    topcoder.cpp:42: error: no matching function for call to ‘sort(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, )’
    /usr/include/c++/3.4.3/bits/stl_algo.h:2575: note: candidates are: void std::sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator > >, _Compare = bool (BinaryCardinality::*)(int, int)]
    count 앞에 static이 빠지면
    topcoder.cpp: In static member function ‘static bool BinaryCardinality::comp(int, int)’:
    topcoder.cpp:36: error: cannot call member function ‘int BinaryCardinality::count(int)’ without object
    topcoder.cpp:36: error: cannot call member function ‘int BinaryCardinality::count(int)’ without object
    topcoder.cpp:37: error: cannot call member function ‘int BinaryCardinality::count(int)’ without object
    topcoder.cpp:37: error: cannot call member function ‘int BinaryCardinality::count(int)’ without object
    topcoder.cpp:38: warning: control reaches end of non-void function
    에러가 발생합니다.


    16년 전 link
  • ILyoan
    ILyoan

    C++에서 class 의 맴버함수는 눈에 보이지 않지만 기본적으로 첫번째 전달인자로 this포인터를 받게 되어있습니다.
    따라서 sort에서 요구하는 콜백함수(??)의 정의와 다르게 되어 호출이 되지 않습니다. 타입 미스매치지요..
    class 내에서 함수를 static으로 선언하면 this pointer가 전달인자로 넘어가지 않기 때문에 사용가능한것 같습니다


    16년 전 link
  • ILyoan
    ILyoan

    아.. 그리고 count에서 에러는
    static 함수에서 맴버변수에 바로 접근할 수 없듯이..(this 포인터가 없으므로 어느 객체의 맴버변수인지 알 수 없죠..)
    static이 아닌 맴버함수를 바로 호출할 수도 없습니다 (역시 전달인자에 this포인터가 없기때문에)


    16년 전 link
  • JongMan
    JongMan

    위에 졸룡님이 잘 설명해 주셨는데, 좀 더 부연해 보겠습니다. :)
    여기에 보면 sort 함수의 정의는

    template <class RandomAccessIterator, class StrictWeakOrdering>
    void sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering comp);
    

    으로 되어있습니다. C++ 컴파일러는 sort 가 호출될 때마다, sort 에 주어진 인자에 따라서 각각 다른 sort 함수의 실제 구현을 만들어 냅니다. 이 때 StrictWeakOrdering 이 함수인지, 클래스인지, 혹은 미지의 무엇인가 인지는 중요하지 않습니다. sort 는 단지 comp(a, b) 형식으로 함수를 호출해서 bool 값을 돌려받는 방식으로만 comp 를 사용합니다.
    예를 들어 우리가

    vector<int> a;
    ...
    sort(a.begin(), a.end(), greater<int>());
    

    이라고 호출한다면, sort 함수의 (RandomAccessIterator = vector::iterator, StrictWeakOrdering = greater) 인 버전(인스턴스라고도 할 수 있겠네요) 이 생겨나는 것이지요.
    여기에 우리가 greater 같은 클래스 외에도 bool comp(int a, int b); 같은 함수를 넘길 수 있는 것도, 이 경우에는 StrictWeakOrdering 이란 타입은 함수 포인터가 되기 때문입니다. 정확하게는 bool(*)(int,int) 타입이 됩니다.
    그런데 StrictWeakOrdering 에 현재 클래스의 멤버인 함수를 넘기게 되면, StrictWeakOrdering 은 현재 클래스의 멤버 함수에 대한 포인터가 됩니다. bool (CurrentClass::*)(int,int); 가 되지요. "member function pointers" 에 대해서 검색해 보시면 아실 수 있겠지만, 이들은 직접 호출하는 것이 불가능합니다. 해당하는 오브젝트에 달아서 호출을 해 줘야 하지요. 예를 들어 이렇게요:

    (instance).*(member_function_pointer)
    

    그런데 당연히 sort 함수는 우리 클래스의 인스턴스가 있는지 모르므로 호출을 할 수 없고, 따라서 컴파일 에러가 됩니다.
    쓰는건 쉽지만 이해하기 어려운 C++ STL 의 세계가 너무 명확하게 드러나는, 간단하지만 심오한 질문이군요. -_-;
    도움이 되셨길~ :)
    덧) 물론, binary_function 을 상속하지 않아도 클래스를 세 번째 인자로 넘기는 것이 가능합니다.


    16년 전 link
  • sooshia
    sooshia

    최고입니다!
    고맙습니다. ^^


    16년 전 link
  • sooshia
    sooshia

    고맙습니다! ^^


    16년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.