Search code examples
c++c++11c++03size-tsize-type

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 is the unsigned integer type of the result of the sizeof operator as well as the sizeof... operator and the alignof operator (since C++11). It's defined in the following headers:

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

To my understanding, the type returned by these operators is implementation-defined.

What I want is to define a custom size_t in order to avoid pulling unnecessary stuff from any of the headers mentioned above in a .cpp file of mine, since in my file I only need std::size_t.

In C++11 and above, I thought I could use the following alias:

using size_t = decltype(sizeof(1));

However, I'd like to define a size_t type for pre-C++11 compilers in a portable/cross-platform way.

So is there a portable way to define size_t for pre-C++11?


Solution

  • Well theoretically, if listing of all possible (unsigned) candidates for size_t doesn't bother you, you could make use of 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]


    Edit:

    Workaround for compilers which differentiate unsigned long from unsigned long long despite the fact that they're assuming 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]