Matt
Matt

Reputation: 22133

What is the best way in C++ to have a compile-time constant depend on a type's size?

I was thinking one of these:

#if sizeof(size_t) == 8
const size_t foo = 12345;
#elif sizeof(size_t) == 4
const size_t foo = 123;
#else
#error "Unsupported size_t size"
#endif

or

template <int S> class Foo { static const size_t foo = 0; };
template <> class Foo<8> { static const size_t foo = 12345; };
template <> class Foo<4> { static const size_t foo = 123; };
const size_t foo = Foo<sizeof(size_t)>::foo;

Also, how can I throw a compile-time error using the second method?

Upvotes: 1

Views: 377

Answers (3)

rcgldr
rcgldr

Reputation: 28911

Use the type for the first and second member of a defined structure and get the offset of the second member to get the size of the first member (this assumes no padding between first and second member, the first member is guaranteed to have the same address as the structure).

#define ofs(s,m)   (size_t)&(((s *)0)->m)

typedef struct S_{
size_t a;       /* type to get the size of */
size_t b;       /* make this same type as above */
}S;

int main()
{
size_t c;
    c = ofs(S,b);   /* get size of S.a */
    return(0);
}

Upvotes: 0

ouah
ouah

Reputation: 145899

With g++ you can also use the following predefined macros:

__SIZEOF_SIZE_T__
__SIZEOF_INT__
__SIZEOF_LONG__

(and so on for the other types, see the documentation for a complete list).

For example:

#if __SIZEOF_SIZE_T__ == 8
const size_t foo = 12345;
#elif __SIZEOF_SIZE_T__ == 4
const size_t foo = 123;
#else
#error "Unsupported size_t size"
#endif

Upvotes: 1

Jon
Jon

Reputation: 437504

The solution with the class template is a good idiomatic way of doing this (the first alternative would also not work, so it's no contest between these two candidates).

To cause a compile-time error, simply do not define the template for all sizes:

template <int S> class Foo;

The compiler will then complain that the template is not defined for the offending value of sizeof(size_t).

It would also help to change the name from Foo to something like Environment_Where_sizeof_int_is -- you 'd get more immediately understandable compiler errors in practice.

Upvotes: 4

Related Questions