Предисловие: Меня раздражает, что ответ помечается как дубликат, фактически не проверяя, решает ли он проблему. Я задавал этот вопрос раньше, но не получилось. В частности, на этот вопрос нет ответа Реализация оператора Matlab’s двоеточие: в классе шаблонов выражений C ++. Это фиксированное количество переменных по сравнению с переменным количеством переменных + переменная комбинация диапазонов целых и целых значений. Если вы все еще думаете правильное направление, то, пожалуйста, предоставьте правильное решение моей заявленной проблемы или просто не помечайте его как дубликат, если вы не можете сделать это.
=> Пожалуйста, проверьте, отвечает ли он на мой вопрос, прежде чем вы нажмете эту двойную кнопку. Благодарю.
Я пытаюсь найти самый элегантный способ определения битовой маски. Эта битовая маска является целым числом и определяет видимость объектов на карте (32 уровня, поэтому биты 0..31 определяют видимость на каждом из 32 уровней). Помощник по созданию битовых массивов должен иметь возможность обрабатывать список целых чисел переменной длины, а также целочисленные диапазоны — И любую их комбинацию.
Например. тогда это может выглядеть так:
int visibilityMask = CreateVisibilityMask ([1..12], 16, 22);
Я думаю, что это действительно сложно. Но разве это невозможно?
По словам Сариена Ответ:
class MaskCreator
{
public:
MaskCreator& AddRange(int from,int to){
for(int i= from; i<=to; ++i){
m_list.push_back(i);
}
return *this;
}
MaskCreator& Add(int i){
m_list.push_back(i);
return *this;
}
MaskCreator& AddMulti( varargstuff ){
m_list.push_back(i);
return *this;
}
unsigned int GetMask();
private:
vector<int> m_list;
}
// usage:
unsigned int mask = MaskCreator().Add(3).Add(7).AddRange(16,25).AddMulti(28,30,31).GetMask();
очевидно, что AddMulti может заменить Add;
Сделайте это VisibilityMask (Range (1, 12)). Добавьте (16) .Add (22), и это будет легко.
Вам нужно только предоставить конструктор и функцию Add с перегрузкой для объекта Range (или двух целых) и для одного типа int. Если вы вернете текущий объект, вы можете связать вызовы следующим образом.
Вы также можете перегрузить оператор<< или operator (), если вы хотите более красивый синтаксис. Но я не думаю, что это хорошая идея. Я бы перегрузил только те для вывода (<<) и функторы (()), чтобы сделать ваш код более читабельным.
Возможно, вы могли бы перегружать оператор запятой или некоторые такие махинации, но я не рекомендую это. Придерживайтесь идиоматического C ++, даже если это означает, что Range (1, 12) теперь на 4 символа больше, чем [1..12]. Вы также не должны использовать функции с переменным числом (см. Вот).
может быть с помощью Varags
Я не использую их часто может быть список Vararg содержат векторы?
Если да, вы можете сделать что-то вроде этого:
std::vector<int> SingleIndices( int vararglist)
{
std::vector<int> vec;
/// push all ints
return vec;
}
std::vector<int> Range(int from, int to)
{
std::vector<int> vec;
for(int i= from; i<=to; ++i){
vec.push_back(i);
}
return vec;
}int CreateVisibilityMask( vectorvarargs );
//usage:
unsigned int mask = CreateVisibilityMask(Range(1,5),SingleIndices(8,9,23), Range(25, 30));
в целом это кажется чрезмерным и не очень эффективным.
Еще одна приятная опция, которая пришла мне в голову, — это просто использовать список var-arg int в следующей форме:
int mask = getBitMask(1, 4, 6,-10, 15, 20,-24);
затем вы обрабатываете аргументы и находите отрицательное число, тогда это означает, что все индексы между последним числом и абсолютным значением текущего числа образуют диапазон.
Единственным недостатком является то, что нет семантической проверки времени компиляции, которая запрещает такие вещи, как
int mask = getBitMask(-2, 4, 6); // allthough this may be valid and just mean bit 0 to 2
или же
int mask = getBitMask(4, -6, -10);