2017-11-14 3 views
0

바이트 배열을 템플릿 유형에 따라 값으로 결합하는 유틸리티 함수를 만듭니다.std :: vector 용 템플릿 반복자

현재 크고 작은 엔디안을 처리하기 위해 한 쌍의 순방향 반복기와 한 쌍의 역 반복기를 사용할 수있는 두 가지 오버로드 된 함수가 있습니다.

템플릿 기반 벡터 반복기를 사용하고 두 함수를 하나로 줄일 수 있습니까?

Failed to specialize function template 'T Utils::combine_bytes(const Iter &, const Iter &)' 

답변

3

당신은 당신의 반복자에 의해 참조 유형이 unsigned char입니다 보장하기 위해 static_assert를 사용할 수 있습니다. 그런 다음에 걸쳐 반복되는 컨테이너의 종류에 대해 걱정할 필요가 없습니다 :

template <typename T, typename Iter> 
inline T combine_bytes(Iter start, Iter end) 
{ 
    static_assert(std::is_same<std::decay_t<decltype(*start)>, unsigned char>::value, 
        "Must use unsigned char"); 
    T ret; 
    std::copy(start, end, reinterpret_cast<unsigned char *>(&ret)); 

    return ret; 
} 

당신이 그것에 인 동안, 당신은 당신이 방금하지 않은 경우 일부 런타임이 있는지 std::distance(begin, end) == sizeof(T)를 만들기 위해 검사를 추가 할 수 있습니다 예제를 짧게 지키려면 그만 두십시오.

+0

이 방법은 SFINAE를 사용합니까? 나는 추측하고있다. – ctzdev

+0

이것을 컴파일하려면'static_assert'에서'unsigned char &'로 체크 할 타입을 변경해야합니다. 그래서 이것은 다음과 같이 보입니다 :'static_assert (std :: is_same ::, "unsigned char을 사용해야합니다)", – ctzdev

+1

@ctzdev 'decltype (* start)'대신'std :: decay_t '을 사용할 수 있습니다. 그것은 기술적으로'unsigned char &'를 사용하는 것보다 정확합니다. 왜냐하면 읽기 전용 이터레이터를 받아 들일 것이기 때문입니다. 그러나 그 차이는 사소한 것입니다. –

2

내가

을 다음과 같이 SFINAE를 사용하여, 당신이 뭔가를 쓸 수 있다고 가정 :

template <typename T, typename Iter> 
inline T combine_bytes(std::vector<unsigned char>::Iter const &start, 
         std::vector<unsigned char>::Iter const &end, 
         bool bigendian) 
{ 
    T ret; 
    std::copy(start, end, reinterpret_cast<unsigned char *>(&ret)); 

    return ret; 
} 

내가 얻는 컴파일 오류는 다음과 같습니다

예를 들어

, 이것은 내가하고 싶은 것입니다

template <typename T, typename Iter> 
inline typename std::enable_if< 
     std::is_same<Iter, std::vector<unsigned char>::iterator>{} 
    || std::is_same<Iter, std::vector<unsigned char>::reverse_iterator>{}, 
    T >::type combine_bytes (Iter const & start, 
          Iter const & end, 
          bool bigendian) 
{ 
    T ret; 
    std::copy(start, end, reinterpret_cast<unsigned char *>(&ret)); 

    return ret; 
} 

다음과 같습니다. 일반 템플릿 유형 Iter에 대한 함수를 정의하고 Iterstd::vector<unsigned char>::iterator 또는 std::vector<unsigned char>::reverse_iterator

+0

Miles Budnek의 접근 방식에 비해이 접근법에 추가 혜택이 있습니까? – ctzdev

+1

@ctzdev - 꼭 그런 것은 아닙니다. 당신의 요구 사항에 달려 있습니다. 다른 유형을 위해 다른 함수를 준비한다면, 모호성을 피하거나 잘못된 버전이 선호되는 것을 피하기 위해'std :: enable_if'를 사용하는 것이 더 나을 것이라고 생각합니다. 유형의 집합에서만 사용해야하는 간단한 케이스가 있다면,'static_assert()'가 더 간단하고 충분히 좋은 해결책이라고 생각합니다. – max66