2012-04-23 3 views
2

std :: map에 필요한 연산자 <() 메서드에 문제가 있습니다. 나는 다음과 같이 보이는 복합 키와 구조체를 사용하고 있습니다 : 나는 4 개 값을 가진 복합 키를 사용하고자 도입,하지만 난 운영자이를 달성하는 방법을 알고하지 않기 때문에std 맵 복합 키

struct MyKey { 
    std::string string1; 
    std::string string2; 
    std::string string3; 
    unsigned int uint1; 

    friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
    { 
    return mk1.string1 < mk2.string1 && mk1.string2 < mk2.string2 && 
      mk1.string3 < mk2.string3 && mk1.uint1 < mk2.uint1; 
    } 
} 

< 방법. 한 번에 하나의 값만 저장된다는 것을 알았습니다!

누구나 올바른 조건이 어떻게 생겼는지 말할 수 있습니까?

미리 감사드립니다.

답변

8

표준 라이브러리의 연관 컨테이너는 같은 std::map, std::set, std::multiset, std::multimap로, std::bitset 요소의 순서가 operator<의 구현이 strict weak ordering를 수행해야 함을 의미 Strict Weak Ordering을 따라야 할 것을 요구하고 있습니다. 그래서 하나의 구현이 될 수있다 :

friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
{ 
    if (mk1.string1 != mk2.string1) 
     return mk1.string1 < mk2.string1; 

    else if (mk1.string2 != mk2.string2) 
     return mk1.string2 < mk2.string2; 

    else if (mk1.string3 != mk2.string3) 
     return mk1.string3 < mk2.string3; 

    else 
     return mk1.uint1 < mk2.uint1; 
} 

아니면로 구현할 수 있습니다 :이 솔루션에서

friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
{ 
    auto const & t1 = std::tie(mk1.string1, mk1.string2, mk1.string3, mk1.uint1); 
    auto const & t2 = std::tie(mk2.string1, mk2.string2, mk2.string3, mk2.uint1); 
    return t1 < t2; 
} 

, std::tie 함수는 두 개의 튜플 t1와 전달 된 인수의 참조 t1가 생성, 대신 에 대해 operator<을 오버로드하여 t1t2을 비교하십시오. 튜플의 operator<은 전적으로 — 엄격한 약한 주문이 달성되는 요소 ..

2

난 당신이 운영자 < 반드시 엄격한 약한 순서를 구현하지 않는다는 점에서 문제가 있다고 생각을 비교합니다. 이 거짓이고 B<A이 거짓 인 조합이 너무 많습니다 (ABMyKey입니다). 이는 AB과 같은 것으로 해석됩니다.

2
구현의 문제는 고려, 안정적이지 점이다

... 평가

return mk1.string1 < mk2.string1 && mk1.string2 < mk2.string2 && 
     mk1.string3 < mk2.string3 && mk1.uint1 < mk2.uint1; 

... { "a", "a", "a", 1 } < { "a", "b", "a", 1 } = a<a && ... = false && ... = false

...하지만 { "a", "b", "a", 1 } < { "a", "a", "a", 1 } = a<a && ... = false && ... = false

따라서 둘 중 어느 하나도 같지 않은데도 다른 하나보다 적게보고됩니다. map에 있습니다.

작업 솔루션 :이 한 번만 각 필요한 문자열 비교를 할 간결하고 효율적 ...

friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
{ 
    int x; 
    return (x = mk1.string1.compare(mk2.string1)) ? x < 0 : 
      (x = mk1.string2.compare(mk2.string2)) ? x < 0 : 
      (x = mk1.string3.compare(mk2.string3)) ? x < 0 : 
      mk1.uint1 < mk2.uint1; 
}