2017-06-13 115 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__(但是,請考慮文檔中的警告,該宏不應直接使用,並且不在所有平臺上提供)。在其他編譯器上,你會使用別的東西。

相關問題