2017-10-22 10 views
2

이 스레드에서 설명한 것과 비슷한 상황이 있습니다 : Getting around Boost Multi-Index container's constant elemets.부스트 멀티 인덱스 항목의 비 인덱스 필드를 수정하는 가장 좋은 방법은 다음과 같습니다. vs mutable 수정

struct Data { 
    Controller controller; 
    const int indexed_data; 
} 

내 인덱스 데이터가 변경되지 않습니다,하지만 컨트롤러가 수행합니다 즉, 나는 boost multi index container이 같은 구조체를 들고있다. 그래서, 내 첫 번째 방법은 내가 modify 호출에 필요한 모든 수행했다 :

container.modify(it, [](auto& data) { 
    data.controller.nonConstFunction(); 
}); 

은 분명히이 나를 위해 일을하지만, 예외가 람다 내부에서 발생합니다 때이 방법의 행동을 이해하기 위해 몇 가지 테스트를 수행했다 (이 내 경우에 일어날 것), 나는 결과에 놀랐습니다 : 당신은 컨테이너의 내용을 인쇄하는 경우이 후

struct employee { 
    int id; 
    std::string name; 
} 

typedef multi_index_container< 
    employee, 
    indexed_by< 
     ordered_unique<BOOST_MULTI_INDEX_MEMBER(employee,int,id)>> 
    > 
> employee_set; 

employee_set es;  
es.insert(employee{0,"Joe"}); 
es.insert(employee{1,"Carl"}); 
es.insert(employee{2,"Robert"}); 
es.insert(employee{4,"John"}); 

try { 
    auto it = es.find(4); // John 
    es.modify(it, [](auto& employee) { 
     employee.id = 1; // Same ID of Carl, should be erased 
     throw std::runtime_error("test"); 
    }); 
} catch (const std::runtime_error& err) { 
    // handle error... 
} 

, 당신은 얻을 :

0 Joe 
1 Carl 
2 Robert 
1 John 

예외를 던지지 않고 직원의 ID를 이미 존재하는 ID로 변경하는 것만으로 인덱스에 대한 히트가 감지되고 수정중인 직원이 지워집니다.

내가 말했듯이, 나는 컨테이너의 키를 변경하지 않지만 이에 대해 알아 낸 후에 걱정된다. 이게 라이브러리 버그 야? 인덱스의 유효하지 않은 상태로 이어질 수있는 다른 상황이 있습니까? 또한 "유효하지 않은"항목 중 하나를 수동으로 삭제/수정하는 것 이외에 유효한 상태로 인덱스를 "다시 처리"하는 방법을 찾을 수 없었습니다. 그 (다시 내 자신의 경우에가는)에서 별도로

실제로 내 컨트롤러에 메소드를 호출 할 modify 가장 좋은 방법을 사용하고, 또는 나는 thread beforementioned의 조언을 따라 내 컨트롤러 mutable를 선언해야합니까? 후자는 나를 위해 매우 위험한 것처럼 보입니다. 아무래도 mutable을 선언하여 색인을 쉽게 망칠 수 있기 때문에, 방금 전에 말했듯이 안전한 방법은 방금 너무 안전하지 않은 것으로 판명되었습니다.

답변

2

modify의 동작이 Jon Kalb pointed my attention to a closely related problem in 2016까지 12 년 이상 안정적 이었기 때문에이 문제를 제기 한 것은 주목할 가치가 있습니다.

간략히 말하자면 modify은 요소 제공 키가 변경되지 않는 한 사용자 제공 수식어가 던져지지 않을 것으로 예상합니다. 사용자가 알아챈 것처럼 정의되지 않은 동작이 발생합니다. 문서에 이렇게 나와 있습니다 (이탤릭체 내) :

예외 안전 : 기본. 일부 사용자 제공 작업 (예외 : mod 제외)에 의해 예외가 발생하면 position이 가리키는 요소가 지워집니다.

버그인지 설계상의 결함인지는 논쟁의 여지가 있지만 어쨌든 최근에 구현이 변경되어 your use case will now result in the element being erased이됩니다.

예외 안전 : 기본을 문서를 읽을 때이 업데이트 된 동작은 곧 부스트 1.66 릴리스 (2017년 12월)에서 사용할 수 있습니다. 일부 사용자 제공 작업 (mod 포함)에 의해 예외가 발생하면 position이 가리키는 요소가 지워집니다.

그 동안 수정자를 수정 후 throws - protects에서 보호해야합니다. modify의 새로운 동작이 절실히 필요한 경우 Boost.MultiIndex 소스 코드를 다운로드하고 로컬 Boost 설치를 패치 할 수 있습니다.

+0

감사합니다. 나는 당신이 강조한 발췌문을 이해하는 데 약간의 어려움을 겪었 음을 고백합니다. 실제로 그것은 내 문제와 관련이 깊었습니다. 어쨌든,'mod'를 실행할 때 어떤 키도 수정하지 않는다고 가정 할 때, 제가 언급 한 다른 스레드에서 스스로 제안한 것처럼'modify'를 사용하거나'mutable' 컨트롤러를 선언하겠습니까? –

+2

글쎄요, 안전과 성능 사이에는 트레이드 오프가 있습니다. '수정'은 일관성을 검사하는 (즉, 키가 수정되지 않았 음을 확인하는) 고비용의 작업이며, '변경 가능'하는 것은 오버 헤드가 없습니다. 프로파일 링이 더 많은 성능이 필요하다는 것을 나타낼 때까지'modify'를 할 것입니다. –