2012-03-25 3 views
2

나는 이런 식으로 뭔가를 보이는 템플릿 컨테이너 클래스가 있습니다컴파일 타임에 사소한 소멸자를 감지하는 방법은 무엇입니까?

template <class ItemType> class MyContainer 
{ 
public: 
    [... various methods omitted for brevity...] 

    void Clear() 
    { 
     ItemType defaultItem; 
     for (int i=0; i<_numValidItems; i++) _itemArray[i] = defaultItem; 
     _numValidItems = 0; 
    } 

    void FastClear() 
    { 
     _numValidItems = 0; 
    } 

private: 
    int _numValidItems; 
    ItemType * _itemArray; 
}; 

당신이 볼 수 있듯이, 지우기() 메소드는 유형의 경우, 예를 들어에 필요한 기본 상태로 컨테이너의 각 항목을 재설정 개별 항목에는 Clear() 호출이 해제되기를 원하는 내부 리소스가 동적으로 할당됩니다.

FastClear()도 이름에서 알 수 있듯이 단순히 _numValidItems를 0으로 설정하고 실제로는 아무 항목도 건드리지 않으므로 더 빠릅니다 (O (N) 대신 O (1)). 배열 이것은 POD 스타일의 ItemType에 적합하지만 예를 들어 그렇게 좋지는 않습니다. 파일 핸들 유형.

내 질문은 SFINAE 또는 유사한 컴파일러에서 ClearClear()에 대한 동의어, 즉 ItemType에 사소한 소멸자가있는 것이 안전하다는 것을 컴파일 타임에 결정할 수있는 방법이 있습니까? 그런 식으로 호출 코드는 Clear 대신 FastClear()를 호출하여 스피드 업을 얻는 것을 기억할 필요가 없으므로 자동으로 작동합니다.

또한, 더 어렵게 만들기 위해서 ... Boost/TR1/C++ 11에 의존성을 추가하지 않고도이 작업을 수행하고 싶습니다.

답변

0

나는 과 함께 Boost Type Traits과 함께 갈 것입니다. 나는 그것이 당신의 질문에 아주 가깝게 대답한다고 생각합니다. Include를 원하지 않는다면, Boost를 사용하여 영감을 얻어서 언제나 직접 구현할 수 있습니다. 결국 SFINAE를 사용합니다.

4

소멸자를 호출 할 수있는 적절한 방법을 (그래서 (is_pod 호출) 또는 has_trivial_destructor()가 나를 위해 좋은 옵션이없는 것은) 것이다

void Clear() 
{ 
    for (int i = 0; i < _numValidItems; ++ i) 
    { 
     _itemArray[i].~ItemType(); 
    } 
    _numValidItems = 0; 
} 

(위 -O2 또는) GCC 4.6에 최적화입니다 소멸자가 사소한 경우에는 루프를 제거하십시오 (4.2에 대해서는 확실하지 않으므로 직접 확인하십시오). 내 버전

0000000000000000 <_ZN11MyContainerISt4pairIddEE5ClearEv>: 
    0: c7 07 00 00 00 00  mov DWORD PTR [rdi],0x0 
    6: c3      ret  

그리고 GCC 4.2이 이미 TR1과 함께 번들 이후, 나는하지를 생산하면서 예를 들어, 나타내고 itemtype std::pair<double, double>에 동일로, 클리어()의 버전은

0000000000000000 <_ZN11MyContainerISt4pairIddEE8BadClearEv>: 
    0: 8b 0f     mov ecx,DWORD PTR [rdi] 
    2: 85 c9     test ecx,ecx 
    4: 7e 34     jle 3a <_ZN11MyContainerISt4pairIddEE8BadClearEv+0x3a> 
    6: 83 e9 01    sub ecx,0x1 
    9: 48 8b 57 08    mov rdx,QWORD PTR [rdi+0x8] 
    d: 31 c0     xor eax,eax 
    f: 48 83 c1 01    add rcx,0x1 
    13: 48 c1 e1 04    shl rcx,0x4 
    17: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0] 
    1e: 00 00 
    20: 48 c7 04 02 00 00 00 mov QWORD PTR [rdx+rax*1],0x0 
    27: 00 
    28: 48 c7 44 02 08 00 00 mov QWORD PTR [rdx+rax*1+0x8],0x0 
    2f: 00 00 
    31: 48 83 c0 10    add rax,0x10 
    35: 48 39 c8    cmp rax,rcx 
    38: 75 e6     jne 20 <_ZN11MyContainerISt4pairIddEE8BadClearEv+0x20> 
    3a: c7 07 00 00 00 00  mov DWORD PTR [rdi],0x0 
    40: c3      ret  

을 생산 std::tr1::has_trivial_destructor을 사용할 수없는 이유를 알아보십시오.

관련 문제