2009-12-17 3 views
0

Я пытаюсь изучить C++, выполнив все «способ C++». Я пишу программу, где у меня есть все эти известные значения (во время компиляции). Вот моя проблема:std :: vector из известных последовательностей

В моем конструкторе я хочу проверить, является ли переданное значение (int) одним из 2,4,8,16 или 32 и выдает ошибку аналогично. Я, хотя о:

  1. сделать массив стилей C или Интс
  2. создания вектора, прежде чем вручную и interating через него, чтобы проверить
  3. сделать список? Раньше я никогда не использовал списки.

Что я действительно хочу сделать, это создать константный вектор в отдельном заголовочном файле, однако это не представляется возможным.

Что является самым элегантным способом для проверки?

Также аналогичным образом можно создать вектор с заданным количеством известных значений (во время компиляции) в заголовке? Если я могу сделать const std::string a_str("a string");, я не понимаю, почему я не могу использовать подобную технику для векторов.

+0

«Я не понимаю, почему я не могу использовать подобную технику для векторов». Списки инициализации для классов. Я считаю, что это запланированная функция «C++ 0x». Не в стандарте еще ... –

ответ

7

Что случилось с:

if (!(n == 2 || n == 4 || n == 8 || n == 16 || n == 32)) 
{ 
    // no! 
} 

Если вы хотите "C++ путь", статический массив должен делать, с find:

template <typename T, size_t N> 
T* endof(T (&pArray)[N]) 
{ 
    return &pArray[0] + N; 
} 

static const int OkNumbers[] = {2, 4, 8, 16, 32}; 
static const int* OkNumbersEnd = endof(OkNumbers); 
if (std::find(OkNumbers, OkNumbersEnd, n) == OkNumbersEnd) 
{ 
    // no! 
} 

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

+0

он хочет сделать это «C++ way» – hhafez

+1

Это не код на C++? Думаю, любой, кто создал список, чтобы проверить несколько цифр, слишком много работает. – GManNickG

+0

+1 для KISS --- – Qberticus

6

Это немного трюк, но я считаю, что это работает:

if (n & (n-1) != 0) 
{ 
    // not a power of two 
} 
+0

Я понял, что он хотел бы только 5 номеров, перечисленных в OP. Возможно, проверка диапазона сделает его подходящим. – GManNickG

+0

приятный и элегантный, но не работает с исключением 64, 128 и т. Д. – hhafez

+0

'0 == 0x0000' не является силой двух. '(0-1) == -1 == 0xffff' и' 0x0000 & 0xffff == 0x0000 == 0', который не является ** '! = 0'. Так что что-то в вашей логике ошибочно. – ndim

1

Если вы действительно ищете делать это с помощью вектора и хотите хорошие операции присваивания имеют вид на повышение :: приписывать.

Но вы просто действительно не хотите, чтобы сделать это с помощью вектора;)

Edit: Я только что видел ваш «во время компиляции». Подумайте, почему это невозможно: std::vector не является встроенным. Чтобы иметь механизм для использования некоторого интеллектуального назначения, подобного этому, требуется встроенная поддержка для всего языка и каждого пользовательского типа. Даже если вам не нужна поддержка основного языка и вы можете сделать это с помощью шаблонов, это не будет соответствовать общему стилю STL.

+0

Является ли строка встроенным? – devin

+0

std :: string не является встроенным типом, а код, который вы указали в вопросе, не создает строку во время компиляции. Он создает строку во время выполнения и инициализирует ее строковым литералом типа C. std :: string просто имеет такой хороший способ инициализации, какой вектор нет. C++ 0x представит списки инициализаторов, которые позволят вам выполнить 'std :: vector v = {1, 2, 3};' или 'std :: vector v2 = {" 1 "," 2 "," 3 "};' –

+0

№ Конструктор, который вы указываете, принимает const char * в качестве аргумента. Этот указатель берется из строкового литерала «строка». Строковые литералы «встроены». – pmr

0

Используйте обычный массив C, моя C ржавые, но здесь идет

int array[] = {2,4,8,16,32}; 

/* now loop over the array and check */ 

for(i = 0; i< size_of_array ; i++) { 
    if (array[i] == input_int) 
    /* you get the idea ..... */ 
0

Это не может соответствовать контексту того, что вы пытаетесь сделать, но вы можете использовать перечисление.

Поскольку это знание времени компиляции, я буду считать, что эти переданные значения важны во время компиляции. Используя перечисление, вызывающие не пытаются выяснить, какое магическое число перейдет в вашу функцию.

typedef enum 
{ 
    Value1 = 2, 
    Value2 = 4, 
    Value4 = 8, 
    Value5 = 16, 
    Value6 = 32 

} MyMagicType; 

void MyFunction(MyMagicType theType) 
{ 
... 
} 

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

2

Если мы говорим о немного вертел sillyness, вот моя попытка:

if ((n & 0x3E) != n || (n & n - 1) != 0) 
    throw std::runtime_error("not a power of two less than or equal to 32"); 

Бит вертел sillyness ОЧЕНЬ C/C++, но только «элегантный», если изящными вы имеете в виду «, как несколько циклов процессора, как абсолютно возможный и как можно более краткий синтаксис ». Используйте поиск в словаре или явную проверку (например, std :: find в ответе GMan), в противном случае.

Читаемость почти всегда предпочтительна для такого рода причудливости.

Смежные вопросы