在编译时根据最大可能数确定索引类型

时间:2014-06-28 11:22:03

标签: c++ templates c++11

我尝试制作index_type_<N>类型,该类型将根据type返回索引的N,其中N是索引的最大数量可以去。

例如:

index_type_<32>::type index1; //uint8_t
index_type_<64000>::type index2;  //uint16_t
index_type_<18446744073709551>::type index3; //uint64_t

我有以下代码拒绝编译,我无法在错误消息中搜索Google,但我无法确定原因,但这些代码似乎与我的情况无关。

    #include <iostream>

template<size_t N, typename T = void>
struct index_type_;

template<size_t N>
struct index_type_<N, typename std::enable_if<N <= 256, uint8_t>::value>
{
    typedef uint8_t type;
};
template<size_t N, typename T = void>
struct index_type_;

template<size_t N>
struct index_type_<N, typename std::enable_if<N <= 65536, uint16_t>::value>
{
    typedef uint16_t type;
};

template<size_t N>
struct index_type_<N, typename std::enable_if<N <= 4294967296, uint32_t>::value>
{
    typedef uint32_t type;
};

template<size_t N>
struct index_type_<N, typename std::enable_if<N <= 18446744073709551616ULL, uint64_t>::value>
{
    typedef uint64_t type;
};

int main()
{
    index_type_<32>::type index1;
    index_type_<232122>::type index2;
    index_type_<992532523>::type index3;
    index_type_<4213662352328854>::type index4;

    std::cout << "index1:" << sizeof(index1) << std::endl;
    std::cout << "index2:" << sizeof(index2) << std::endl;
    std::cout << "index3:" << sizeof(index3) << std::endl;
    std::cout << "index4:" << sizeof(index4) << std::endl;
}

错误和示例代码可以在这里找到:

http://ideone.com/SJdKjr

任何帮助都会非常感激,我觉得我错过了一些明显的东西。

2 个答案:

答案 0 :(得分:6)

您的所有专业都不明确。例如。哪一个是以下的最佳选择?

template <std::size_t N>
struct Foo {
    // Specialization 1
};

template <std::size_t N>
struct Foo<N> {
    // Specialization 2
};

int main() {
    Foo<1> foo; // Error: partial specialization 'Foo<N>' does not
                //        specialize any template arguments.
}

尝试这样的事情:

template <std::uintmax_t N>
struct index_type {
    using type = std::conditional_t<N <= 255, std::uint8_t,
                 std::conditional_t<N <= 63535, std::uint16_t,
                 std::conditional_t<N <= 4294967295, std::uint32_t,
                 std::conditional_t<N <= 18446744073709551615ULL, std::uint64_t,
                 std::uintmax_t>>>>;
};

template <std::uintmax_t N>
using index_type_t = typename index_type<N>::type;

用法:

index_type_t<64000> test; // unsigned int

答案 1 :(得分:3)

通过numeric_limits使用类型列表和递归测试:

#include <cstdint>
#include <limits>
#include <type_traits>

namespace detail
{
    template<class T>
    struct delay { using type = T; };

    template<class T, T t, class... IntTypes>
    struct select_int_type
    {
        static_assert(sizeof...(IntTypes) > 0,
                      "No integer type sufficiently big found.");
    };

    template<class T, T t, class Head, class... Tail>
    struct select_int_type<T, t, Head, Tail...>
    {
        using type = typename std::conditional<
              t <= std::numeric_limits<Head>::max()
            , delay<Head>
            , select_int_type<T, t, Tail...>
        >::type::type;
    };
}

template<std::uintmax_t N>
using select_uint_type =
    typename detail::select_int_type<decltype(N), N,
          std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t
        , std::uintmax_t
    >::type;

用法示例:

#include <iostream>

int main()
{
    select_uint_type<32> index1;
    select_uint_type<232122> index2;
    select_uint_type<992532523> index3;
    select_uint_type<4213662352328854> index4;

    std::cout << "index1:" << sizeof(index1) << std::endl;
    std::cout << "index2:" << sizeof(index2) << std::endl;
    std::cout << "index3:" << sizeof(index3) << std::endl;
    std::cout << "index4:" << sizeof(index4) << std::endl;
}

您可以通过其他别名模板轻松添加签名类型:

template<std::intmax_t N>
using select_int_type =
    typename detail::select_int_type<decltype(N), N,
          std::int8_t, std::int16_t, std::int32_t, std::int64_t
        , std::intmax_t
    >::type;

(我认为make_signed因为基于值的选择而存在问题