#c #struct #custom-data-type
#c #struct #пользовательский тип данных
Вопрос:
Я искал похожие вопросы, но не нашел своего ответа.
В принципе, мне нужно объявить / определить переменную, которая имеет определенный диапазон от 0 до 64 включительно. Должен ли я использовать перечисление? Структура? Могу ли я сделать это при объявлении переменной? Я хочу использовать его в структуре.
Конечно, я мог бы написать несколько проверок if / else, но должен быть более простой способ без создания массива [64].
Комментарии:
1. Включен 64 или нет? Если нет, вы можете использовать битовое поле.
2. Существуют целочисленные типы с фиксированной шириной.
3. Включены как 0, так и 64. Если это поможет, предполагается, что он представляет стеки инвентаря в Minecraft. Максимальный размер стека равен 64. 0 пуст.
4. Это зависит от того, как вы хотите его использовать и почему вы этого хотите? Например, это для экономии места или для обнаружения ошибок вне диапазона?
Ответ №1:
Если вам нужно только ограниченное целое число, вы можете просто проверить диапазон в конструкторе. Вот так:
#include <stdexcept>
template<int max>
class ConstrInt {
public:
ConstrInt(int val) {
if (val > max)
throw std::out_of_range("");
m_val = val;
}
int value() const {
return m_val;
}
private:
int m_val;
};
int main(){
ConstrInt<64> a{1};
auto aa = a.value();
ConstrInt<64> b{65}; // exception for > 64
}
Комментарии:
1. На самом деле я надеялся, что смогу использовать символ (меньшего размера) и ограничить его значением [0, 64].
2. Не могу ли я определить перечисление с диапазоном от 0 до 64 включительно, не вводя вручную каждое значение?
3. @Kampfkeksgeschwader: Перечисления имеют минимальный диапазон, который уже округлен до чуть ниже следующей степени двойки (т.Е. 127), и вы также пропускаете арифметические операции целочисленного типа.
Ответ №2:
Должен ли я использовать перечисление?
Я не понимаю, как это было бы полезно.
Структура?
Если вы хотите определить пользовательский тип данных, тогда вам нужно определить класс (структуры — это классы).
Могу ли я сделать это при объявлении переменной?
Вы можете определить переменные пользовательских типов данных, если это то, что вы имеете в виду.
Конечно, я мог бы написать несколько проверок if / else, но должен быть более простой способ без создания массива [64].
Нет необходимости создавать массив только для проверки, находится ли значение в пределах диапазона. Вот пример проверки:
if (x >= 0 amp;amp; x <= 64)
Ответ №3:
Вы могли бы определить класс, содержащий an unsigned char
, и заставить его обтекать точно так же, как это делают встроенные целочисленные типы без знака, так что 0 - 1
это приводит к 64
и это 64 1
приводит к 0
.
Пример:
template<unsigned End = 64>
class usmall {
public:
// implicit conversion constructor, making sure the value is in the range [0, End]
usmall(unsigned char v = 0) : data(v % (End 1)) {}
// implicit user defined conversion operator
operator unsigned char () const { return data; }
// pre increment and decrement operators
usmallamp; operator () { if(data==End) data = 0; else data; return *this; }
usmallamp; operator--() { if(data==0) data = End; else --data; return *this; }
// post increment and decrement operators
usmall operator (int) { usmall rv(*this); *this; return rv; }
usmall operator--(int) { usmall rv(*this); --*this; return rv; }
// common arithmetic operators
usmallamp; operator =(const usmallamp; rhs) {
data = (data rhs.data) % (End 1);
return *this;
}
usmallamp; operator-=(const usmallamp; rhs) {
if(data < rhs.data) data = (End 1);
data -= rhs.data;
return *this;
}
usmallamp; operator*=(const usmallamp; rhs) {
data = (data * rhs.data) % (End 1);
return *this;
}
usmallamp; operator/=(const usmallamp; rhs) {
data /= rhs.data;
return *this;
}
private:
unsigned char data;
};
// free arithmetic functions
template<unsigned End>
auto operator (const usmall<End>amp; lhs, const usmall<End>amp; rhs) {
usmall rv(lhs);
rv = rhs;
return rv;
}
template<unsigned End>
auto operator-(const usmall<End>amp; lhs, const usmall<End>amp; rhs) {
usmall rv(lhs);
rv -= rhs;
return rv;
}
template<unsigned End>
auto operator*(const usmall<End>amp; lhs, const usmall<End>amp; rhs) {
usmall rv(lhs);
rv *= rhs;
return rv;
}
template<unsigned End>
auto operator/(const usmall<End>amp; lhs, const usmall<End>amp; rhs) {
usmall rv(lhs);
rv /= rhs;
return rv;
}
Пример:
#include <iostream>
int main() {
usmall foo = 3;
usmall bar = 30;
usmall baz = foo * bar;
std::cout << static_cast<unsigned>(baz) << 'n'; // prints 25
}