C ++中是否有完整且可移植的所有不同整数类型的列表?

时间:2016-07-15 14:34:52

标签: c++ integer

我想实现一个处理所有简单C ++类型的函数(也是STL容器和更多类型,但它们不会让我头疼),通用函数处理所有其他类型,如下所示:

template <typename T>
void dostuff(T& arg)
{ cout << "generic version" << endl; }
void dostuff(int& arg)
{ cout << "something useful" << endl; }
void dostuff(unsigned int& arg)
{ cout << "something slightly different" << endl; }
void dostuff(short& arg)
{ cout << "something slightly different again" << endl; }
// ...and so on for all integer types...

这里我将自己限制为整数类型,因为它们会造成所有麻烦。当然,如果我为同一类型实现两次函数,编译器会抱怨。混合unsigned intstd::size_t等内容时会发生这种情况。它适用于我的系统,但不能在32位平台上编译。我理解这个问题,但我不知道如何实现便携式解决方案。

我认为最系统的方法是使用std :: int8_t(std :: uint8_t,16,32,64)类型系列,因为它们不会重叠并且旨在覆盖可用范围。事实证明,这还不够,如以下代码所示:

#include <type_traits>
#include <cstdint>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    cout << "SIZE:" << endl;
    cout << "sizeof(unsigned long)      = " << sizeof(unsigned long) << endl;
    cout << "sizeof(unsigned long long) = " << sizeof(unsigned long long) << endl;
    cout << "sizeof(std::size_t)        = " << sizeof(std::size_t) << endl;
    cout << "sizeof(std::uint64_t)      = " << sizeof(std::uint64_t) << endl;
    cout << endl;

    cout << "SIGNED?" << std::boolalpha << endl;
    cout << std::is_signed<unsigned long>::value << endl;
    cout << std::is_signed<unsigned long long>::value << endl;
    cout << std::is_signed<std::size_t>::value << endl;
    cout << std::is_signed<std::uint64_t>::value << endl;
    cout << endl;

    cout << "SAME?" << endl;
    cout << std::is_same<unsigned long, unsigned long long>::value << endl;
    cout << std::is_same<unsigned long, std::size_t>::value << endl;
    cout << std::is_same<unsigned long, std::uint64_t>::value << endl;
    cout << std::is_same<unsigned long long, std::size_t>::value << endl;
    cout << std::is_same<unsigned long long, std::uint64_t>::value << endl;
    cout << std::is_same<std::size_t, std::uint64_t>::value << endl;
}

在我的带有clang 3.8的64位MacOS系统上,它提供了以下输出:

SIZE:
sizeof(unsigned long)      = 8
sizeof(unsigned long long) = 8
sizeof(std::size_t)        = 8
sizeof(std::uint64_t)      = 8

SIGNED?
false
false
false
false

SAME?
false
true
false
false
true
false

所以我有四个64位无符号整数类型,但它们实际上只指两个不同的类型。还有更多候选人,例如std::uintptr_tstd::ptrdiff_tstd::uint_fast64_t,我甚至不知道该列表是否完整。 对于我来说,哪些类型相同的定义看起来是任意的,但我发现,对于我所面临的确切问题,我们希望将longlong long视为不同。

问题:有没有办法为不同整数类型的详尽列表实现上述功能,这样我就不会在不同的平台上遇到麻烦?如果是这样,这个清单是什么?如果不是,那么实现所需行为的最佳方法是什么(处理所有整数类型,未知类型的有意义的默认行为,便携式解决方案)?

2 个答案:

答案 0 :(得分:3)

由于您尝试针对每种特定的整数类型执行不同的操作,即使您可以枚举程序中的所有类型,也无法构成特定的特殊逻辑。

相反,我要建议的是根据需要实现说shortintunsigned等的特殊逻辑,并设置一个静态断言{{1在您的主模板中是is_integral<T>,并显示一条消息,表明它是使用不支持的整数类型调用的,需要确定和编写自定义逻辑。

答案 1 :(得分:2)

专注于所有整数类型通常是一个非常糟糕的主意。根据评论中的讨论,我假设静态调度的大小&amp;类型的签名适合你。以下是如何做到的:

#include <iostream>
#include <type_traits>

template <typename T, unsigned Size, bool Signed>
struct foo_impl;

template <typename T>
struct foo_impl<T, 1, false>
{
    static void foo (T & x) { std::cout << x << " is unsigned 8-bit" << std::endl; }
};

template <typename T>
struct foo_impl<T, 1, true>
{
    static void foo (T & x) { std::cout << x << " is signed 8-bit" << std::endl; }
};

template <typename T>
struct foo_impl<T, 2, false>
{
    static void foo (T & x) { std::cout << x << " is unsigned 16-bit" << std::endl; }
};

// more specializations ...

template <typename T>
void foo (T & x)
{
    // dispatch based on size & signedness
    foo_impl<T, sizeof(T), std::is_signed<T>::value>::foo(x);
}

int main ( )
{
    char a = 5;
    std::uint8_t b = 6;
    unsigned short c = 7;

    foo(a);
    foo(b);
    foo(c);
}

Live on ideone