2017-06-13 47 views
12

std::size_t通常用于数组索引和循环计数。根据定义,std::size_tsizeof运算符的结果的无符号整数类型,以及sizeof...运算符和alignof运算符(自C++ 11起)。它在下面的头文件中定义:如何定义一个自定义的跨平台size_t类型?

  • <cstddef>
  • <cstdio>
  • <cstdlib>
  • <cstring>
  • <ctime>
  • <cwchar>

要我取消这些操作符返回的类型是实现定义的。

我希望的是,以避免任何在.cpp文件矿山上面提到的头拉不必要的东西,因为在我的文件,我只需要std::size_t定义一个自定义size_t

在C++ 11以上,想到可以使用下面的别名:

using size_t = decltype(sizeof(1)); 

然而,我想在便携式以限定size_t型预C++ 11个编译器/跨平台的方式。

那么是否有一种便捷的方式来定义pre-C++ 11的size_t

+3

你或许应该标记这个问题,C++ 03或C++ 98,但不是C++ 11,对不对? – Rakete1111

+12

*为什么*你不想包含任何标准头文件?它们通常不那么大,并且不会显着影响编译时间。而且,如果定义了'size_t'的实际上没有任何函数定义,那就意味着不会为它们生成任何代码。你能否通过定义你自己的类型来详细说明你想解决的*实际问题? –

+5

'cstddef'是一个很小的标题,就符号而言。命名空间污染真的太多了吗? – StoryTeller

回答

3

那么从理论上说,如果所有可能的(无符号)候选人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]


编辑:

针对不同编译器的解决方法unsigned longunsigned long long尽管他们假定sizeof(unsigned long) == sizeof(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; 

[live demo]

+1

老兄这是什么样的魔术?!?!?!?!?! – 101010

+0

@ 101010你可以叫我胡迪尼;) –

0

不幸的是,“实现定义”包括头文件,而不仅仅是编译器本身。如果你看一下[expr.sizeof],他们似乎只是以此来表明:

#include <cstddef> 
+0

OP已经列出了'' – NathanOliver

+0

我知道。我只是指出C++标准有点奇怪,因为它们不需要内置的语言功能(如sizeof和[typeid](http://eel.is/c++draft/expr.typeid ))必须由内置类型支持(不需要包含)。 –

4

据我所知,你所列出的仅有的两个跨平台的方式来获得size_t:包括从标准头的定义,或decltype(自C++ 11以来)。但两者都明确无法提供给您。

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

相关问题