Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42899

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:

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?

Upvotes: 14

Views: 1611

Answers (3)

W.F.
W.F.

Reputation: 13988

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]

Upvotes: 5

eerorika
eerorika

Reputation: 238331

As far as I know, you've listed the only two cross-platform ways to get size_t: Include the definition from standard header, or decltype (since C++11). But both are explicitly unavailable to you.

The third option is manual porting i.e. use pre-defined macros to detect the environment, and choose the correct typedef from a manually maintained list of typedefs. For example, on GCC you might use __SIZE_TYPE__ (however, consider the warning in the documentation that the macro should not be used directly and that it is not provided on all platforms). On other compilers you would use something else.

Upvotes: 4

David A
David A

Reputation: 394

Unfortunately, "implementation-defined" includes the header files, not just the compiler itself. If you look at [expr.sizeof], they seem to suggest just using this:

#include <cstddef>

Upvotes: 0

Related Questions