2014-05-19 6 views
2

정의 된 방식으로 유형 펀칭을 처리하는 템플릿 함수를 작성하려고 했으므로이 두 함수를 생각해 냈습니다. 첫 번째는 객체를 가져 와서 다른 객체로 전달합니다. 두 유형 모두 POD 및 동일한 크기를 보장합니다. 두 번째는 단순히 포인터를 가져오고 (void *처럼) 포인터가 POD 유형인지 확인합니다. 문제는 비 const 포인터를 전달하면 첫 번째 함수가 대신 사용된다는 것입니다. 이것을 처리하는 가장 좋은 방법은 무엇입니까?함수 템플릿 오버로드 해결

template <class TO, class FROM> 
FORCE_INLINE TO punning_cast(const FROM &input) 
{ 
    static_assert(std::is_pod<TO>::value, "TO must be POD"); 
    static_assert(std::is_pod<FROM>::value, "FROM must be POD"); 
    static_assert(sizeof(TO) == sizeof(FROM), "TO and FROM must be the same size"); 

    TO out; 
    std::memcpy(&out, &input, sizeof(TO)); 
    return out; 
} 

template <class TO, class FROM> 
FORCE_INLINE TO punning_cast(const FROM *input) 
{ 
    static_assert(std::is_pod<TO>::value, "TO must be POD"); 
    static_assert(std::is_pod<FROM>::value, "FROM must be POD"); 

    TO out; 
    std::memcpy(&out, input, sizeof(TO)); 
    return out; 
} 
+0

아마도'유형 이름 표준 : enable_if <표준 : : :!

한이 (공통) 문제에 대한 해결책은 구조체의 기능을 포장하고 그 중 하나를 선택하는 도우미 함수를 추가하는 것입니다 :: value, TO> :: type'이 이전의 리턴 타입으로 도움이 될 수 있습니다. – WhozCraig

+0

@WhozCraig 나는 이미 대답했다. –

+0

(단지 이것을 지적 해 주므로 대답을 훔쳤다.) –

답변

3

기능 템플릿 mix weirdly with overloading.

가능한 용액 (아닌 고유)은 (따라서 제

#include <type_traits> 

template <class TO, class FROM> 
FORCE_INLINE typename enable_if<!is_pointer<FROM>::value, TO>::type 
    punning_cast(const FROM &input) { ... } 

template <class TO, class FROM> 
FORCE_INLINE typename enable_if<is_pointer<FROM>::value, TO>::type 
    punning_cast(const FROM input) { ... } 

dissambiguation을 달성하는, 예를 들면 포인터 타입 초와 바이스 마찬가지 enalbing 각 기능의 선언 enable_if를 사용하는 것 참조와 포인터 사이에 있음)은 this one

+0

"함수 템플릿에 과부하가 없다"는 것이 완전히 정확하지만 +1이다. 나머지는. –

+0

@MooingDuck 너무 단순화가 너무 많습니까? 나는 [함수 템플릿 과부하 해결] (http://stackoverflow.com/a/22411782/2567683)로 들어가 겠지만 그 질문의 범위를 벗어나야 만한다. (오해를 막기 위해 그것을 제거해야한다고 생각한다. ?) –

+0

필자는 "함수 템플릿이 이상하게 오버로드되는 경우가 있습니다. [link] (http://www.gotw.ca/gotw/049.htm)를 참조하십시오." –

3

면책 조항 : C++ 11 이상에서는 Nikos Athanasiou's answer을 사용하는 것이 좋습니다. is_pointer

template <class TO, class FROM> 
struct punning_cast_impl 
{ 
    static FORCE_INLINE TO cast(const FROM &input) 
    { 
     static_assert(std::is_pod<TO>::value, "TO must be POD"); 
     static_assert(std::is_pod<FROM>::value, "FROM must be POD"); 
     static_assert(sizeof(TO) == sizeof(FROM), "TO and FROM must be the same size"); 

     TO out; 
     std::memcpy(&out, &input, sizeof(TO)); 
     return out; 
    } 
}; 

template <class TO, class FROM> 
struct punning_cast_impl<TO, FROM*> 
{ 
    static FORCE_INLINE TO cast(const FROM *input) 
    { 
     static_assert(std::is_pod<TO>::value, "TO must be POD"); 
     static_assert(std::is_pod<FROM>::value, "FROM must be POD"); 

     TO out; 
     std::memcpy(&out, input, sizeof(TO)); 
     return out; 
    } 
}; 

template<class TO, class FROM> 
TO FORCE_INLINE punning_cast(const FROM& input) 
{ 
    return punning_cast_impl<TO, FROM>::cast(input); 
} 

int main() 
{ 
    double d1 = 50.0; 
    int64_t i1 = punning_cast<int64_t>(d1); // calls version #1 

    double d2 = 100.0; 
    int64_t i2 = punning_cast<int64_t>(&d2); // calls version #2 
} 
+0

+1 당신은 저를 때렸습니다. 'punninc_cast_impl :: cast' 함수에 형식 인수에'const'를 추가합니다. 그렇지 않으면'const'에 대한 포인터를 실제 인수로 사용할 수 없습니다. –

+0

@ Cheersandhth.-Alf Oops; 어떻게 든 그것을 복사에서 잃어 버렸습니다. 감사. – dlf

+0

+1 스포츠맨 쉽. 더 길지 만,이 답변은 좋게 조정되며, 문제는 현재의 문제에 따라 선택할 수 있습니다. 잘 했어. –