如何定义自定义 cross-platform size_t 类型?

How to define a custom cross-platform size_t type?

std::size_t is commonly used for array indexing and loop counting. By definition, std::size_tsizeof 运算符以及 sizeof... 运算符和 alignof 运算符结果的无符号整数类型(C++11 起).它的定义如下 headers:

据我了解,这些运算符返回的类型是 implementation-defined。

我想要定义一个自定义 size_t 以避免从我的 .cpp 文件中上面提到的任何 headers 中提取不必要的东西,因为在我的文件我只需要 std::size_t.

在 C++11 及更高版本中,我认为我可以使用以下别名:

using size_t = decltype(sizeof(1));

但是,我想以 portable/cross-platform 的方式为 pre-C++11 编译器定义一个 size_t 类型。

那么有没有一种可移植的方法来为 pre-C++11 定义 size_t

不幸的是,"implementation-defined" 包括头文件,而不仅仅是编译器本身。如果你看看 [expr.sizeof],他们似乎建议只使用这个:

#include <cstddef>

据我所知,您列出了仅有的两种 cross-platform 获取 size_t 的方法:包括来自标准 header 的定义,或 decltype(自 C++ 11).但两者都对您明确不可用。

第三个选项是手动移植,即使用 pre-defined 宏来检测环境,并从手动维护的 typedef 列表中选择正确的 typedef。例如,在 GCC 上,您可能会使用 __SIZE_TYPE__(但是,请考虑文档中的警告,即不应直接使用宏并且并非在所有平台上都提供该宏)。在其他编译器上,您会使用其他东西。

理论上,如果 size_t 的所有可能(未签名)候选人列表不打扰您,您可以使用 SFINAE:

template <class T, class N = void, bool = sizeof(T) == sizeof(sizeof(T))>
struct TL { 
    typedef typename N::type type;
};

template <class T, class N>
struct TL<T, N, true> {
    typedef T type;
};

typedef TL<unsigned short,TL<unsigned int, TL<unsigned long, TL<unsigned long long> > > >::type SizeT;

[live demo]


编辑:

尽管假设 sizeof(unsigned long) == sizeof(unsigned long long):

,但区分 unsigned longunsigned long long 的编译器的解决方法
template <class U>
U *declptrval(U);

template <class U>
char is_exact(U *);

template <class U>
short is_exact(...);

template <class T, class N = void, bool = sizeof(is_exact<T>(declptrval(sizeof(T))))==sizeof(char)>
struct TL { 
    typedef typename N::type type;
};

template <class T, class N>
struct TL<T, N, true> {
    typedef T type;
};

typedef TL<unsigned short,TL<unsigned int, TL<unsigned long, TL<unsigned long long> > > >::type SizeT;

[live demo]