const or not const, that's the question here! :-)

Discussion in 'C++' started by Adem24, Jun 13, 2008.

  1. Adem24

    Adem24 Guest

    The compiler which I have to use in a project doesn't like
    the following construct. It says: 'bitset' : invalid template argument.
    It means that it wants only a static-like const N as a template argument,
    ie. it doesn't accept a const variable that was initialized
    from an auto variable (here i), for passing it as a template
    argument to bitset<n>.

    Is this a compiler limitation or is my code not standard conform?
    Can you think of any workaround construct to achieve this
    or an alternate functionality with such a compiler?

    Of course if I change the line to read for example
    const size_t N = 1U << 16;
    then it compiles ok. But I need to loop 22 times here...

    #include <bitset>
    void f()
    {
    for (size_t i = 1; i <= 22; ++i)
    {
    const size_t N = 1U << i;
    bitset<N> bv;

    bv.set(7);
    //...
    }
    }
    Adem24, Jun 13, 2008
    #1
    1. Advertising

  2. Adem24

    Kai-Uwe Bux Guest

    Adem24 wrote:

    > The compiler which I have to use in a project doesn't like
    > the following construct. It says: 'bitset' : invalid template argument.
    > It means that it wants only a static-like const N as a template argument,
    > ie. it doesn't accept a const variable that was initialized
    > from an auto variable (here i), for passing it as a template
    > argument to bitset<n>.
    >
    > Is this a compiler limitation or is my code not standard conform?
    > Can you think of any workaround construct to achieve this
    > or an alternate functionality with such a compiler?
    >
    > Of course if I change the line to read for example
    > const size_t N = 1U << 16;
    > then it compiles ok. But I need to loop 22 times here...
    >
    > #include <bitset>
    > void f()
    > {
    > for (size_t i = 1; i <= 22; ++i)
    > {
    > const size_t N = 1U << i;
    > bitset<N> bv;


    Your code is wrong. This N is not a compile time constant. Templates only
    work with those.

    You might want to have a look into dynamic_bitset from boost or
    vector<bool>.


    > bv.set(7);
    > //...
    > }
    > }



    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jun 13, 2008
    #2
    1. Advertising

  3. Adem24

    Eric Pruneau Guest

    "Adem24" <> a écrit dans le message de news:
    g2ug98$533$...
    > The compiler which I have to use in a project doesn't like
    > the following construct. It says: 'bitset' : invalid template argument.
    > It means that it wants only a static-like const N as a template argument,
    > ie. it doesn't accept a const variable that was initialized
    > from an auto variable (here i), for passing it as a template
    > argument to bitset<n>.
    >
    > Is this a compiler limitation or is my code not standard conform?
    > Can you think of any workaround construct to achieve this
    > or an alternate functionality with such a compiler?
    >
    > Of course if I change the line to read for example
    > const size_t N = 1U << 16;
    > then it compiles ok. But I need to loop 22 times here...
    >
    > #include <bitset>
    > void f()
    > {
    > for (size_t i = 1; i <= 22; ++i)
    > {
    > const size_t N = 1U << i;
    > bitset<N> bv;
    >
    > bv.set(7);
    > //...
    > }
    > }
    >


    Your code cannot compile. N must be a compile time evaluatable constant. In
    your case, N is constant but unknow to the compiler at compile time because
    of i.

    ----------------
    Eric Pruneau
    Eric Pruneau, Jun 13, 2008
    #3
  4. Adem24

    kwikius Guest

    "Kai-Uwe Bux" <> wrote in message
    news:g2ugif$5as$...
    > Adem24 wrote:
    >
    >> The compiler which I have to use in a project doesn't like
    >> the following construct. It says: 'bitset' : invalid template argument.
    >> It means that it wants only a static-like const N as a template argument,
    >> ie. it doesn't accept a const variable that was initialized
    >> from an auto variable (here i), for passing it as a template
    >> argument to bitset<n>.
    >>
    >> Is this a compiler limitation or is my code not standard conform?
    >> Can you think of any workaround construct to achieve this
    >> or an alternate functionality with such a compiler?
    >>
    >> Of course if I change the line to read for example
    >> const size_t N = 1U << 16;
    >> then it compiles ok. But I need to loop 22 times here...
    >>
    >> #include <bitset>
    >> void f()
    >> {
    >> for (size_t i = 1; i <= 22; ++i)
    >> {
    >> const size_t N = 1U << i;
    >> bitset<N> bv;

    >
    > Your code is wrong. This N is not a compile time constant. Templates only
    > work with those.


    You could probably set this up fairly simply to use compile time recursion.
    Use a functor templated on N which calls N-1 and specialize it for zero (or
    other way up ) case etc...

    regards
    Andy Little
    kwikius, Jun 13, 2008
    #4
  5. Adem24

    Kai-Uwe Bux Guest

    kwikius wrote:

    >
    > "Kai-Uwe Bux" <> wrote in message
    > news:g2ugif$5as$...
    >> Adem24 wrote:
    >>
    >>> The compiler which I have to use in a project doesn't like
    >>> the following construct. It says: 'bitset' : invalid template argument.
    >>> It means that it wants only a static-like const N as a template
    >>> argument, ie. it doesn't accept a const variable that was initialized
    >>> from an auto variable (here i), for passing it as a template
    >>> argument to bitset<n>.
    >>>
    >>> Is this a compiler limitation or is my code not standard conform?
    >>> Can you think of any workaround construct to achieve this
    >>> or an alternate functionality with such a compiler?
    >>>
    >>> Of course if I change the line to read for example
    >>> const size_t N = 1U << 16;
    >>> then it compiles ok. But I need to loop 22 times here...
    >>>
    >>> #include <bitset>
    >>> void f()
    >>> {
    >>> for (size_t i = 1; i <= 22; ++i)
    >>> {
    >>> const size_t N = 1U << i;
    >>> bitset<N> bv;

    >>
    >> Your code is wrong. This N is not a compile time constant. Templates only
    >> work with those.

    >
    > You could probably set this up fairly simply to use compile time
    > recursion. Use a functor templated on N which calls N-1 and specialize it
    > for zero (or other way up ) case etc...


    Yes one could do that. But why? You end up with some monstrous incantation
    that will fill your screen with book size error messages if you get a tiny
    detail wrong; and for which gain? The algorithms underlying bitset<N> are
    mostly just bit fiddling iterated over a vector of unsigned long (int?)
    anyway. I would be rather surprised if it matters performancewise whether
    the length of that buffer is fixed at compile time or at run time.

    I love templates, I really do; but in a case like this, I think they would
    make the code worse (e.g., harder to maintain and change).


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jun 13, 2008
    #5
  6. Adem24

    kwikius Guest

    Re: const or not const, that's the question here! :)

    On Jun 13, 10:42 pm, Kai-Uwe Bux <> wrote:
    > kwikius wrote:
    >
    > > "Kai-Uwe Bux" <> wrote in message
    > >news:g2ugif$5as$...
    > >> Adem24 wrote:

    >
    > >>> The compiler which I have to use in a project doesn't like
    > >>> the following construct. It says: 'bitset' : invalid template argument..
    > >>> It means that it wants only a static-like const N as a template
    > >>> argument, ie. it doesn't accept a const variable that was initialized
    > >>> from an auto variable (here i), for passing it as a template
    > >>> argument to bitset<n>.

    >
    > >>> Is this a compiler limitation or is my code not standard conform?
    > >>> Can you think of any workaround construct to achieve this
    > >>> or an alternate functionality with such a compiler?

    >
    > >>> Of course if I change the line to read for example
    > >>>    const size_t N = 1U << 16;
    > >>> then it compiles ok. But I need to loop 22 times here...

    >
    > >>> #include <bitset>
    > >>> void f()
    > >>> {
    > >>>     for (size_t i = 1; i <= 22; ++i)
    > >>>       {
    > >>>         const size_t N = 1U << i;
    > >>>         bitset<N> bv;

    >
    > >> Your code is wrong. This N is not a compile time constant. Templates only
    > >> work with those.

    >
    > > You could probably set this up fairly simply to use compile time
    > > recursion. Use a functor templated on N which calls N-1 and specialize it
    > > for zero (or other way up ) case etc...

    >
    > Yes one could do that. But why?


    Only one way to find out....

    <... usual inertia elided ...>

    regards
    Andy Little
    kwikius, Jun 14, 2008
    #6
  7. Adem24

    Andy Little Guest

    Re: const or not const, that's the question here! :)

    kwikius wrote:
    > On Jun 13, 10:42 pm, Kai-Uwe Bux <> wrote:
    >> kwikius wrote:


    >>> You could probably set this up fairly simply to use compile time
    >>> recursion. Use a functor templated on N which calls N-1 and specialize it
    >>> for zero (or other way up ) case etc...

    >> Yes one could do that. But why?

    >
    > Only one way to find out....
    >
    > <... usual inertia elided ...>


    Apologies That was a bit fierce, however using compile time loop
    unrolling is a useful technique, and the OP was asking why it wasnt
    didnt seem possible. I was merely pointing out that it is possible. In
    some cases the compiler may do loop unrolling for you, but doing it
    explicitly using compile time recursion is one less uncertainty/ layer
    of complexity for the optimiser.

    Interestingly, looking at std::bitset, Its kind of a weird hybrid
    because the length is fixed but many ops are runtime.

    As an example one could add a bitset.flip<Pos>() function to accompany
    bitset.flip(pos). The first version being again easier to optimise and
    all the information re the op is available at compile time unlike the
    runtime parameter, and very usefully, the range can be checked at
    compile time too, so there is no need of a runtime check and possible
    exception, unlike appears to be the case in the runtime flip (which
    throws an exception on out of range). The same applies to many (probably
    nearly all) ops in bitset AFAICS.

    regards
    Andy Lttle
    Andy Little, Jun 14, 2008
    #7
  8. Hi!

    kwikius schrieb:
    > You could probably set this up fairly simply to use compile time recursion.
    > Use a functor templated on N which calls N-1 and specialize it for zero (or
    > other way up ) case etc...


    You could probably fix this fairly simple by using the same size in each
    loop:

    const size_t maxlen = 22;
    bitset<1 << maxlen> bv;
    for (size_t i = 1; i <= maxlen; ++i)
    {
    const size_t N = 1U << i;

    bv.set(7);
    //...
    }

    Frank
    Frank Birbacher, Jun 14, 2008
    #8
  9. Adem24

    Bo Persson Guest

    Re: const or not const, that's the question here! :)

    Andy Little wrote:
    > kwikius wrote:
    >> On Jun 13, 10:42 pm, Kai-Uwe Bux <> wrote:
    >>> kwikius wrote:

    >
    >>>> You could probably set this up fairly simply to use compile time
    >>>> recursion. Use a functor templated on N which calls N-1 and
    >>>> specialize it for zero (or other way up ) case etc...
    >>> Yes one could do that. But why?

    >>
    >> Only one way to find out....
    >>
    >> <... usual inertia elided ...>

    >
    > Apologies That was a bit fierce, however using compile time loop
    > unrolling is a useful technique, and the OP was asking why it wasnt
    > didnt seem possible. I was merely pointing out that it is possible.
    > In some cases the compiler may do loop unrolling for you, but doing
    > it explicitly using compile time recursion is one less uncertainty/
    > layer of complexity for the optimiser.
    >
    > Interestingly, looking at std::bitset, Its kind of a weird hybrid
    > because the length is fixed but many ops are runtime.
    >
    > As an example one could add a bitset.flip<Pos>() function to
    > accompany bitset.flip(pos). The first version being again easier
    > to optimise and all the information re the op is available at
    > compile time unlike the runtime parameter, and very usefully, the
    > range can be checked at compile time too, so there is no need of a
    > runtime check and possible exception, unlike appears to be the case
    > in the runtime flip (which throws an exception on out of range).
    > The same applies to many (probably nearly all) ops in bitset AFAICS.
    >


    Any decent optimizer can do that anyway, when pos is a compile time
    constant. That saves you from modifying the application code when that
    condition changes.


    Bo Persson
    Bo Persson, Jun 14, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page