2012-05-10 2 views
17

그래서 멋진 영구 할당 자 클래스 persistent_alloc<T>을 사용하면 C++ 컨테이너 객체와 문자열을 영구 메모리에 할당 할 수 있습니다.이 객체는 내 프로그램 실행에서 지속될 수있는 mmaped 파일로 백업됩니다. 다음 것.C에서 다른 할당자를 사용하여 객체 복사하기

내 문제는 영구적 인 객체와 비 영구적 인 객체를 혼합하는 작업을 수행하고자 할 때 발생합니다. 예를 들어, 나는

typedef std::basic_string<char, std::char_traits<char>, persistent_alloc<char>> pstring; 

pstring a, b, c; 
std::string x, y, z; 

내가 좋아하는 일을 할 수 있도록하려면이 : 등

if (a == x) 
    a = y; 
c = z + b; 

하고 있지만, pstringstd::string는 관련이없는 종류로 기본적으로는 작동하지 않습니다. 비교에 관한 한, 다음과 같이 정의 할 수 있습니다.

template<typename Alloc1, typename Alloc2> inline bool 
operator==(const std::basic_string<char, std::char_traits<char>, Alloc1> &a, 
      const std::basic_string<char, std::char_traits<char>, Alloc2> &b) 
{ 
    return strcmp(a.c_str(), b.c_str()) == 0; 
} 

... 이제 문자열을 평등과 비교할 수 있습니다. 그러나 이러한 모든 작업을 추가하는 것은 고통스러운 것처럼 보입니다. 표준 라이브러리가 제공해야하는 것처럼 보입니다. 더욱이 할당 연산자와 복사 생성자는 멤버 여야하며 이와 같은 전역 인라인 함수로 정의 할 수 없습니다.

이렇게하는 합리적인 방법이 있습니까? 또는 할당자를 유용하게 지원하기 위해 전체 표준 라이브러리를 효과적으로 다시 작성해야합니까?

+6

이것은 과거 표준위원회에 제출되었습니다. 현재의 할당 자 모델과 그 외의 제한은 [n1850] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1850.pdf)에 나와 있습니다. C++의 할당 자 모델은 잘 정의되어 있지 않으며 실제로 문제가 있습니다 (n1850의 대안은 다른 이유로 문제가 있습니다) –

+2

관련없는 참고 사항 : 유형이'std :: is_trivially_copyable :: value == true'를 사용합니다. 영구 메모리를 정확히 같은 절대 위치 또는 그와 비슷한 위치에 복원하지 않는 한. –

+0

일부 동작이 동일하게 동작하고 일부 동작이 다르게 동작하기를 원합니다. 만약 당신이 그것을 철자하지 않으면 컴파일러는 어떻게 알 수 있습니까? –

답변

7

이 문제를 처리 할 수있는 방법이 있지만 상자 밖에서 조금 생각해야합니다. 당신이 필요로하는 것은 std::string과 할당 자 문자열 모두에 의해 암시 적으로 구성 가능한 중간 유형입니다.

proposal for such a thing before the C++ committee currently이 있습니다. Google-built Apache-licensed implementation that already exists을 기반으로합니다. 그것은 basic_string_ref이라고 불립니다. 기본적으로 문자열의 첫 번째 문자를 가리키는 포인터 인 템플릿 클래스이고 문자열의 길이를 나타내는 크기입니다. 그것은 메모리를 관리하지 않는다는 점에서 진정한 컨테이너가 아닙니다.

정확하게 필요한 것은 무엇입니까?

basic_string_ref 특정 문자 유형 및 특성 유형은 std::basic_string에서 할당 자의과 관계없이 암시 적으로 구성 할 수 있습니다.

모든 비교 연산자는 basic_string_ref으로 정의 할 수 있습니다. std::basic_string에서 암시 적으로 생성 가능하므로 (사실상 생성이 무료 임), 다르게 할당 된 문자열 간의 비교를 위해 투명하게 작동합니다.

과제를 수행하는 것이 다소 까다 롭지 만 할 수 있습니다. 일련의 전환이 필요합니다.

a = pstring{basic_string_ref{y}}; 

물론 가장 예쁜 코드는 아닙니다. 복사 생성자와 대입 연산자 인 std::basic_string을 단순히 할당 자에 종속되지 않도록 변경하는 것이 좋습니다. 하지만 그건 불가능하기 때문에, 이것은 정말로 차선책입니다.당신은 템플릿 함수에 포장도 수 : 물론

template<typename DestAllocator, typename SourceAllocator, typename charT, typename traits> 
std::basic_string<charT, traits, DestAllocator> conv_str(const std::basic_string<charT, traits, SourceAllocator> &input) 
{ 
    return std::basic_string<charT, traits, DestAllocator>{basic_string_ref<charT, traits>{y}}; 
} 

, 당신이 할 수 있다면, 당신은 단지이 작업을 수행 할 수 있습니다이의 한 부분 인 경우

template<typename DestAllocator, typename SourceAllocator, typename charT, typename traits> 
std::basic_string<charT, traits, DestAllocator> conv_str(const std::basic_string<charT, traits, SourceAllocator> &input) 
{ 
    return std::basic_string<charT, traits, DestAllocator>{y.begin(), y.end()}; 
} 

그것은 좋은 것 std::basic_string이므로 해결 방법이 필요하지 않습니다. 그러나 그렇지 않습니다.

+0

이렇게하면 문제가 좀 더 단순 해지지 만 완전히 해결되지는 않습니다. 표준 라이브러리를 변경하지 않고 할당 연산자를 작동시키는 방법은 아직 없습니다. –

+0

@ChrisDodd : 예, 알고 있습니다. 나는 그것을 말했다. 당신은 당신이 원하는 것의 80 %를 얻고 약간의 API 크래프트를 다루거나,'std :: basic_string'를 다시 쓸 수 있습니다. 개인적으로 나는 전자를 제안 할 것이다. –

관련 문제