type
      Units* = SomeUnsignedInt
      BitVecS*[S:static int, B:Units = uint] = object
        Base*: array[S div (sizeof(B) * 8) + int(S mod (sizeof(B) * 8) != 0), 
B] #8,16,32,64
      BitVec*[B:Units] = object
        Base: seq[B]
        size: int
      AnyBitVec[S:static int, B:Units] = (BitVecS[S, B] | BitVec[B])
    
    proc `[]`*[S,B](bv:AnyBitVec[S, B], i:int): int =
      return (bv.Base[i div (B.sizeof * 8)] shr (i and (B.sizeof * 8 - 1)) and 
1).int
    
    func newBitVector*[B](size: int, init = 0): BitVec[B] {.inline.} =
      var blocks = size div (sizeof(B) * 8) + int(size mod (sizeof(B) * 8) != 0)
      result.Base = newSeqOfCap[B](blocks)
      result.Base.setlen(blocks)
      result.size = size
    
    var bv1: BitvecS[20240001]
    
    var y = newBitVector[uint32](1000)
    discard y[0] #this fails
    
    Run

I am trying to write a bitvector lib that has a common implementation for 
static (array) and dynamic (seq) ones, with user defineable base unit of 
storage. For static one I need S (static size) and B (base unit), while for the 
dynamic one I only need B. I tried like in the code above, but when accessing 
any procs on the dynamic one (BitVec), I get "Error: cannot instantiate: 'S'". 
I thought this would work since BitVec doesn't have/need S, but no. I got 
around it by adding the S parameter to the type, and passing a random number as 
generic parameter when calling procs on it, and while this works, it's 
obviously not pretty, and makes me believe there has to be a way to make this 
work cleanly. I was told to use concepts, but I couldn't make that work either, 
and I really don't understand how they work even after reading the doc. But I'd 
like not to use them unless absolutely necessary. Also, on a side note, the 
default generic parameter type I have on BitVecS (B:Units = uint) seems to 
actually work, although I was told it shouldn't. Any idea why it works (in this 
context)?

Reply via email to