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

Is there a complete and portable list of all different integer types in C++?

本文关键字:列表 类型 可移植 整数 是否 C++      更新时间:2023-10-16

我想实现一个处理所有简单C++类型的函数(还有 STL 容器和更多类型,但它们没有给我 headakes),使用处理所有其他类型的泛型函数,如下所示:

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;
}

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

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视为不同。

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

由于您尝试为每个特定的整型类型做一些不同的事情,因此即使您可以枚举程序中的所有类型,也无法编造特定的特殊逻辑。

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

专门针对所有积分类型通常是一个非常糟糕的主意。根据评论中的讨论,我假设对类型的大小和符号进行静态调度会适合您。这是如何完成的:

#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);
}

生活在 ideone 上