2009-10-18 7 views
1

루비와 파이썬에서 메타 프로그래밍의 장점을 보았지만 실제 작업을 위해서는 C++과 C과 같은 저급 언어에 묶여 있었기 때문에 두 가지를 결합하는 매너를 생각하고 있습니다. . 하나의 인스턴스는 임의의 구조/클래스의리스트를 정렬하기위한 간단한 문제로 온다. 예를 들어,커스텀 C++ 전 처리기/타입 넘치는 매크로

struct s{ 
    int a; 
    int b; 
}; 

vector<s> vec; 
for(int x=0;x<10;x++){ 
    s inst; 
    inst.a = x; 
    inst.b = x+10; 
    vec.push_back(inst); 
} 

궁극적으로 최소한의 상용구 코드로 임의로 정렬 할 수 있기를 바랍니다.

sort(vec.begin(),vec.end()); 

아직이 "구조체의"의 비교할 수있는 방법을 쓰는 저를 요구한다 : 나는이 일을 볼 수있는 가장 쉬운 방법은 STL의 종류를 사용하는 것입니다. 내가하고 싶은 것은 :

sort(vec,a ASC,b DESC); 

매우 명확하게 C++가 유효하지 않습니다.

내 꿈을 이루는 가장 좋은 방법은 무엇입니까? 형식 매크로를 사용하면 벡터 요소의 유형이 무엇인지 알 수 있습니다. 전 처리기 매크로를 사용하여 정렬 작업을 수행하는 데 필요한 함수를 작성하는 것이 쉽습니다.

다른 대안은 내 자신의 전처리기를 쓰는 것 같습니다. 이것은 "vec"의 유형을 다시 추론해야만하는 지점까지 잘 작동합니다. 이 작업을 수행하는 쉬운 방법이 있습니까?

컨텍스트 : 적은 코드 = 적은 경쟁, 프로그래밍 경쟁.

답변

2

위를 들면, 당신은 파이썬 람다처럼, 당신의 비교 함수를 인라인으로 작성 Boost.Lambda를 사용할 수 있습니다

using namespace boost::lambda; 

std::sort(vec.begin(), vec.end(), (_1 ->* &s::a) < (_2 ->* &s::a)); 

이 물론 당신이에 의해 정렬되어 있다고 가정합니다.

찾고있는 표현식이 훨씬 복잡한 경우 별도의 함수를 작성하는 것이 좋습니다. Python과 Ruby 같은 언어에서도 클로저를 기본적으로 지원하므로 복잡한 클로저는 어쨌든 꽤 읽을 수 없게됩니다.

경고 : 위의 코드는 테스트되지 않았습니다.

희망이 도움이됩니다.

+0

화려한, 나는 누군가가 이것을 템플릿으로해야만한다는 것을 알았다. 감사! –

-2

표준 라이브러리는 다양한 컨테이너에서 작동하는 많은 유용한 기능을 포함하는 algorithms 헤더를 제공합니다. 당신의 목적을 위해 예제는 다음과 같습니다

bool sCompare(const s & s1, const s & s2) { 
return s1.a+s1.b/1000 < s2/a+s2.b/1000; 
} 

vector<s> vec; 
... 
std::sort(vec.begin(), vec.end(), sCompare); 

종류의 뭔가를 보이는 프로토 타입이 있습니다

template<class Iter, class Op> 
void sort(Iter& start, Iter& stop, Op& op); 

이러한 알고리즘의 대부분은 일부 정렬 된 컨테이너에 특정 (표준 컨테이너의 작동한다 , 일부 연관성 등). 정렬 (및 다른 것들) 배열 (알고리즘의 기초 인 반복자는 배열 요소에 대한 포인터를 최대한 가깝게 에뮬레이트하기 위해 빌드 된 것입니다.)

요컨대 현대 C++를 사용하면 특별한 선행 처리기를 사용하여 수행하려는 작업을 수행하십시오.

현재 std 또는 std :: sort를 사용하고 있다고 선언 한 경우 sort(vec.begin(),vec.end())입니다. 유효한 C++;

+0

/1000은 분명히 여기에서 틀리다. –

2

struct에 대한 비교 연산자 작성에 전념 할 것입니다. 비교 연산자를 정의하는 것의 보너스는 여러 곳에 흩어져있는 여러 람다 비교로 끝나지 않는다는 것입니다. 비교 연산자가 한 번만 필요하기 때문에 논리적 인 장소 (유형과 함께)에서 한 번만 정의하면됩니까?

개인적으로 나는 코드를 한 번 작성하고 특히 쉽게 찾을 수있는 장소를 유지하는 것을 선호합니다. 나는 또한 내가 쓰고있는 언어와 관련하여 관용적 인 코드를 작성하는 것을 선호한다. C++에서는 생성자, 소멸자, 운영자 이하 등이 필요하다. less-than 연산자를 작성한 다음 std::sort(vec.begin(), vec.end())이 올바른 작업을하도록하는 것이 좋습니다. 당신이 비교를 한 다음 네임 스페이스 수준에서 연산자를 제공하기 위해 멤버 함수를 정의하는 경우

struct S { 
    int a, b; 
    bool less_than(S const& other) {...}; 
}; 
bool operator<(S const& left, S const& right) { 
    return left.less_than(right); 
} 

은, 인생은 당신이있을 때 훨씬 더 쉽게 당신이 정말로 명확한 코드를 확인하려면 다음과 같이 할 비교를 부정한다. 예 :

void foo(std::vector<S>& svec) { 
    std::sort(svec.begin(), svec.end(), std::not1(&S::less_than)); 
} 

이 코드는 테스트되지 않았지만 아이디어를 얻을 수 있습니다.

auto q = LINQ(from(x, vec) orderby(ascending x.a, descending x.b)); 

를 또는 쿼리 구문을 좋아하지 않는 경우에, 당신은뿐만 아니라 확장 방법을 사용할 수 있습니다

0

당신이 C++ (11)를 사용하는 경우, 당신은이처럼 정렬 Linq을 사용할 수 있습니다 :

auto q = vec | linq::order_by([](s x) { return x.a; }) 
      | linq::then_by_descending([](s x) { return x.b; }); 

두 기능적으로 동일합니다.