2015-01-24 2 views
1

Я думал, один из них:Каков наилучший способ в C++ иметь постоянную времени компиляции в зависимости от размера шрифта?

#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 

или

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; 

Кроме того, как я могу бросить ошибку во время компиляции, используя второй метод?

+6

Вы можете использовать 'std :: static_assert' во втором методе. – Kevin

+3

'# if' не знает о' sizeof'. Вы можете использовать некоторые макросы из 'limits.h', хотя, например, 'SIZE_MAX'. –

+0

@MattMcNabb Это хороший момент, я забыл об этом. И 'SIZE_MAX' будет работать, только если это фактически' size_t' (или один из других стандартных типов), о котором я забочусь, что не обязательно так. – Matt

ответ

4

Решение с шаблоном класса является хорошим идиоматическим способом выполнения этого (первая альтернатива также не будет работать, поэтому это не соревнование между этими двумя кандидатами).

Чтобы вызвать ошибку во время компиляции, просто не определить шаблон для всех размеров:

template <int S> class Foo; 

компилятора будет жаловаться, что шаблон не определен для значения нарушившего из sizeof(size_t).

Это также поможет сменить имя от Foo на что-то вроде Environment_Where_sizeof_int_is - вы получите более понятные ошибки компилятора на практике.

+0

Спасибо, но это не отвечает на мой главный вопрос. – Matt

+2

@Matt: Я отредактировал, чтобы явно обратиться к нему, хотя, конечно, ядро ​​ответа остается неизменным. – Jon

+0

Только для записи я использую в примерах имена, подобные 'Foo'. – Matt

1

С g++ вы также можете использовать следующие предопределенные макросы:

__SIZEOF_SIZE_T__ 
__SIZEOF_INT__ 
__SIZEOF_LONG__ 

(и так далее для других типов, см documentation для полного списка).

Например:

#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 
+0

Спасибо, но, как я отметил в комментариях, тип, о котором идет речь, необязательно является одним из стандартных типов , – Matt

+1

@Matt Я на самом деле не читал комментарии. Мой ответ также не является стандартным C++, но для тех, кто этого не знает, я думаю, что это может помочь. – ouah

0

использовать тип для первого и второго члена определенной структуры и получить смещение второго элемента, чтобы получить размер первого элемента (это не несет прокладки между первым и второй член, первый член, как гарантируется, имеет тот же адрес, что и структура).

#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); 
}