Bitmasks: Initialize an int bitmask with a variable length list of ints AND int-ranges

StackOverflow https://stackoverflow.com/questions/16360850

  •  14-04-2022
  •  | 
  •  

Pregunta

Foreword: I find it annoying that an answer is marked as duplicate without actually checking if it solves one's problem. I've asked this question before, but didn't succeed. In particular, this question is not answered by Implementing Matlab's colon : operator in C++ expression templates class. It is fixed number of variables vs. variable number of variables + variable combination of ranges of integers and integer values. If you still think the right direction, then please provide a valid solution to my stated problem or just don't mark it simply as duplicate if you can't do so.

=> Please check back if it's answering my question, before you just hit that duplicate button. Thanks.

I'm trying to find the most elegant way to define a bitmask. This bitmask is an integer, and it defines the visibility of objects on a map (32 levels, so bits 0..31 define visibility on each of the 32 levels). The bitmaks creation helper should be able to handle a variable length list of integers, as well as integer ranges - AND any combination of these.

E.g. it could then look like:

int visibilityMask = CreateVisibilityMask([1..12], 16, 22);

I guess this one is really tough. But is it impossible?

¿Fue útil?

Solución

According to Sarien Answer:

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();

obviously the AddMulti could replace the Add;

Otros consejos

Make it VisibilityMask(Range(1, 12)).Add(16).Add(22) and it will be easy.

You only need to provide a constructor and an Add function with an overload for a Range object (or two ints) and for one int. If you return the current object you can chain the calls like this.

You could also overload operator<< or operator() if you want prettier syntax. But I don't think it is a good idea. I would only overload those for output (<<) and functors (()) to make your code more readable.

You could probably overload the comma operator or some such shenanigans but I do not recommend it. Stick to idiomatic C++, even if it means that Range(1, 12) now has 4 characters more than [1..12]. You should also not use variadic functions (see here).

may be by using varags I do not use them often can be a vararg list contain vectors? if yes you can possible do something like this:

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

at all this seems to be over engeneered and not very efficient.

another nice option that came me into mind is simply use a var-arg int list in the followin form:

int mask = getBitMask(1, 4, 6,-10, 15, 20,-24);

then you procesi the args and found a negative numer then this means that all indices between the last number and the abs of current number forms a range.

Only drawback is, that there is no semantic compiletime check that prohibits things like

int mask = getBitMask(-2, 4, 6); // allthough this may be valid and just mean bit 0 to 2

or

int mask = getBitMask(4, -6, -10); 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top