如何定义自定义 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_t
是 sizeof
运算符以及 sizeof...
运算符和 alignof
运算符结果的无符号整数类型(C++11 起).它的定义如下 headers:
<cstddef>
<cstdio>
<cstdlib>
<cstring>
<ctime>
<cwchar>
据我了解,这些运算符返回的类型是 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;
编辑:
尽管假设 sizeof(unsigned long) == sizeof(unsigned long long)
:
,但区分 unsigned long
和 unsigned 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;
std::size_t
is commonly used for array indexing and loop counting. By definition, std::size_t
是 sizeof
运算符以及 sizeof...
运算符和 alignof
运算符结果的无符号整数类型(C++11 起).它的定义如下 headers:
<cstddef>
<cstdio>
<cstdlib>
<cstring>
<ctime>
<cwchar>
据我了解,这些运算符返回的类型是 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;
编辑:
尽管假设 sizeof(unsigned long) == sizeof(unsigned long long)
:
unsigned long
和 unsigned 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;