2016-07-27 1 views
4

정수형이 T (signed 또는 unsigned)라고 가정합니다. 필자는 (컴파일 타임에) std::numeric_limits<T>::max()에 1을 더할 수있는 가장 작은 정수형 (부호가 있거나 부호가없는 것)을 참조하려고합니다 (비 - 넘치는 의미에서 말입니다)."T보다 큰 최소 적분 유형"을 표현하는 방법은 무엇입니까?

그 일을하는 훌륭한 방법은 무엇입니까?

template <typename T> 
constexpr unsigned size_in_bits() { return sizeof(T) * CHAR_BIT; } 

template <typename T> 
using smallest_larger_uint_t = 
    typename boost::uint_t<size_in_bits<T>() + 1>::least; 

을 우리가 뭔가 정수 유형에 대해 작업 할 경우 : 서명되지 않은 유형의

+1

ammm을 .. 'T '의 두 배 크기 인 부호없는 정수형이 아닌가? –

+0

@ NathanOliver OP는 그 값을 유지할 수있는 모든 유형 중 가장 작은 것을 의미한다고 생각합니다. 즉 uint32_t와 uint64_t 중 하나를 선택하면 uint32_t를 선택하십시오. – Borgleader

+0

@Borgleader 의미가 있습니다. 감사. – NathanOliver

답변

2

,이 트릭을 수행

template <typename T, int NumBits> 
using boost_integer_type = 
    typename std::conditional< 
     std::is_unsigned<T>::value, 
     boost::uint_t<NumBits>, 
     boost::int_t<NumBits> 
    >::type; 

template <typename T> 
constexpr unsigned size_in_bits() { return sizeof(T) * CHAR_BIT; } 

template <typename T> 
using smallest_larger_integral_t = 
    typename boost_integer_type<T, size_in_bits<T>() + 1>::least; 

int_t<N>uint_t<N>에 대한 자세한 내용은 documentation for Boost.Integer를 참조하십시오.

+0

참고 :'size_in_bits () + 1'은'boost_integer_type'의 내부에 있어야한다. –

+0

@ DieterLücking : – einpoklum

0

당신은 cstdint에서 유형을 사용하여,이 같은 작업을 수행 할 수 있습니다

template <typename T> 
struct next_type { 
    typedef error_type type; 
}; 

template <> 
struct next_type<std::int32_t> { 
    typedef std::uint32_t type; 
} 

template <> 
struct next_type<std::uint32_t> { 
    typedef std::int64_t type; 
} 

// Add more... 

각 유형에 대한 전문을 추가. 그런 다음 그것을 사용 :

typename next_type<T>::type 

을 당신은 이미 당신이 어떻게 든 자신이 무엇인지 정의해야합니다 error_type을 받고 가능한 최대 유형을 사용 그래서 경우는 true, 그렇지 않은 경우는 전문화됩니다.

std::uint_least32_t과 같이 cstdint에서 _least 유형을 사용하는 것이 더 나을 것입니다.

+0

그러나 어떤 유형인지는 어떻게 알 수 있습니까? 더 커? 예를 들어'int'가'unsigned short'보다 더 큰 최대 값을 갖는다는 보장은 없습니다. – NathanOliver

+0

에서 유형을 사용하는 것이 좋습니다. 그렇지 않으면 옳습니다. –

+0

심지어 _least 유형을 사용하는 경우도 있습니다. 예를 들어 int_least8_t to uint_least8t –

2

당신은 필요한 크기로 정수를 지정하고 그에 따라 선택할 수 있습니다 : 당신이 뭔가 모든 정수 타입에 잘 작동하려면

#include <cstdint> 

namespace Detail { 
    template <std::size_t> struct integer_of_size_undefined {}; 
    template <> struct integer_of_size_undefined<sizeof(int8_t)> { 
     typedef int8_t type; 
    }; 
    template <> struct integer_of_size_undefined<sizeof(int16_t)> { 
     typedef int16_t type; 
    }; 
    template <> struct integer_of_size_undefined<sizeof(int32_t)> { 
     typedef int32_t type; 
    }; 
    template <> struct integer_of_size_undefined<sizeof(int64_t)> { 
     typedef int64_t type; 
    }; 

    template <std::size_t> struct unsigned_integer_of_size_undefined {}; 
    template <> struct unsigned_integer_of_size_undefined<sizeof(int8_t)> { 
     typedef uint8_t type; 
    }; 
    template <> struct unsigned_integer_of_size_undefined<sizeof(int16_t)> { 
     typedef uint16_t type; 
    }; 
    template <> struct unsigned_integer_of_size_undefined<sizeof(int32_t)> { 
     typedef uint32_t type; 
    }; 
    template <> struct unsigned_integer_of_size_undefined<sizeof(int64_t)> { 
     typedef uint64_t type; 
    }; 
} 

template <std::size_t N> 
struct integer_of_size { 
    typedef typename Detail::integer_of_size_undefined<N>::type type; 
}; 

template <std::size_t N> 
struct unsigned_integer_of_size { 
    typedef typename Detail::unsigned_integer_of_size_undefined<N>::type type; 
}; 


#include <type_traits> 

template <typename T> 
struct next_integer { 
    typedef typename std::conditional<std::is_signed<T>::value, 
     typename std::make_unsigned<T>::type, 
     typename integer_of_size<2*sizeof(T)>::type>::type 
     type; 
}; 

int main() 
{ 
    static_assert(std::is_same<next_integer<std::int16_t>::type, uint16_t>::value, 
     "Should be a unsigned 16 bit"); 
    static_assert(std::is_same<next_integer<std::uint16_t>::type, int32_t>::value, 
     "Should be a signed 32 bit"); 

    return 0; 
} 
+0

표준 3 또는 6의 필수 유형이있을 수 있습니까? – einpoklum

+0

아니요, 표준 보증은 없지만 실제로는 ... –

+0

... 그 경우에는 _my_ 코드가 해당 가정을 작성하는 것을 원하지 않습니다. 표준 라이브러리에서 이미 표현 된 것에 의존하고 싶습니다. (또는 최대 부스트, 내 대답과 마찬가지로) 그 지식에 대한 ... – einpoklum

0

, 당신은 여러 단계로 구축 된 특성이 포함 할 수 있습니다. 우리는 비트 형식으로 정수형을 매핑하는 것으로 시작합니다 :

#define CREATE_SIGNED_META_OBJ(x) template <>\ 
    struct signed_integer_type<x> {\ 
     typedef int##x##_t type;\ 
    }; 

#define CREATE_UNSIGNED_META_OBJ(x) template <>\ 
    struct unsigned_integer_type<x> {\ 
     typedef uint##x##_t type;\ 
    }; 

template <std::size_t length> 
struct signed_integer_type; 

template <std::size_t len> 
struct unsigned_integer_type; 

CREATE_SIGNED_META_OBJ(8) 
CREATE_SIGNED_META_OBJ(16) 
CREATE_SIGNED_META_OBJ(32) 
CREATE_SIGNED_META_OBJ(64) 

CREATE_UNSIGNED_META_OBJ(8) 
CREATE_UNSIGNED_META_OBJ(16) 
CREATE_UNSIGNED_META_OBJ(32) 
CREATE_UNSIGNED_META_OBJ(64) 

그런 다음 특성을 자체적으로 작성할 수 있습니다. 우리는

template <typename Int, bool> 
struct get_smallest_for_max_plus_one; 

template <typename Int> 
struct get_smallest_for_max_plus_one<Int, true> { 
    typedef typename signed_integer_type<2*sizeof(Int)*8>::type type; 
}; 

template <typename Int> 
struct get_smallest_for_max_plus_one<Int, false> { 
    typedef typename unsigned_integer_type<sizeof(Int)*8>::type type; 
}; 

template <typename Int> 
using get_fittest_int_type = get_smallest_for_max_plus_one<Int, std::numeric_limits<Int>::min() == 0>; 

지금 우리가 어떤 통합 정수와 직접 get_fittest_int_type을 사용할 수 있습니다 ... 주장 std::numeric_limits<Int>::min() == 0의 값에 우리의 이분법을 적용 할 ... 실행 예 Coliru에서 찾을 수 있습니다. 하지만 일관성을 위하여

, 내가 원하는 작업 ... signed 또는 unsigned 속성을 유지하기 위해이 경우, 당신은 단지 다음과 같이 get_smallest_for_max_plus_one의 전문화를 대체 할 수 원하는 같아요

// Unsigned type, we want to get the smallest unsigned type that can hold max + 1 
template <typename Int> 
struct get_smallest_for_max_plus_one<Int, true> { 
    typedef typename unsigned_integer_type<2*sizeof(Int)*8>::type type; 
}; 

// Signed type, we want the smallest signed type that can hold max + 1 
template <typename Int> 
struct get_smallest_for_max_plus_one<Int, false> { 
    typedef typename signed_integer_type<2*sizeof(Int)*8>::type type; 
}; 
+0

... C++ 표준은 실제로 3 또는 6 크기의 정수 유형이 없음을 보장합니까? – einpoklum

+0

@einpoklum 당신의 의심은 나에게 합당한 것처럼 보입니다. 나는이 사실을 확인하지 않았습니다. 방금 정수 유형이있는 최소 예제를 제공했습니다. 부스트를 기반으로 한 솔루션은 그 점에서보다 다용도로 보입니다! – Rerito

관련 문제