A Template that rejects classes.

Discussion in 'C++' started by Dominic Connor, Pimp, May 9, 2007.

  1. I've got a bit of code that shows which bits of a variable are 1 or 0
    (OK, I'm making assumptions about 8 bit bytes and significance.)

    But what I want to do is only allow this template to be instantiated
    for base types, not classes.
    I am averse to RTTI for this, but I keep thinking there's a bit of
    syntactic sugar that will do it cleanly.
    Solutions of the form "classes are bigger than 64 bits so reject them"
    don't count :)

    template <typename T> string DumpBits (T x)
    {
    unsigned int mask=1;
    int i;
    string s;

    for ( i= 0; i != sizeof(x)*8; i++, mask *=2)
    {
    mask & x ? s = "1" + s : s = "0" + s;
    }
    return s;
    }
     
    Dominic Connor, Pimp, May 9, 2007
    #1
    1. Advertising

  2. Dominic Connor, Pimp wrote:
    > I've got a bit of code that shows which bits of a variable are 1 or 0
    > (OK, I'm making assumptions about 8 bit bytes and significance.)
    >
    > But what I want to do is only allow this template to be instantiated
    > for base types, not classes.
    > I am averse to RTTI for this, but I keep thinking there's a bit of
    > syntactic sugar that will do it cleanly.
    > Solutions of the form "classes are bigger than 64 bits so reject them"
    > don't count :)
    >
    > template <typename T> string DumpBits (T x)
    > {
    > unsigned int mask=1;
    > int i;
    > string s;
    >
    > for ( i= 0; i != sizeof(x)*8; i++, mask *=2)
    > {
    > mask & x ? s = "1" + s : s = "0" + s;
    > }
    > return s;
    > }


    Find a solution to recognize something as a class (SFINAE is used
    along with "a pointer to member" syntax), and invert it. Look on the
    web for "type is a class" template solution.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, May 9, 2007
    #2
    1. Advertising

  3. Dominic Connor, Pimp wrote:
    > I've got a bit of code that shows which bits of a variable are 1 or 0
    > (OK, I'm making assumptions about 8 bit bytes and significance.)
    >
    > But what I want to do is only allow this template to be instantiated
    > for base types, not classes.
    > I am averse to RTTI for this, but I keep thinking there's a bit of
    > syntactic sugar that will do it cleanly.
    > Solutions of the form "classes are bigger than 64 bits so reject them"
    > don't count :)
    >
    > template <typename T> string DumpBits (T x)
    > {
    > unsigned int mask=1;
    > int i;
    > string s;
    >
    > for ( i= 0; i != sizeof(x)*8; i++, mask *=2)
    > {
    > mask & x ? s = "1" + s : s = "0" + s;
    > }
    > return s;
    > }
    >


    That code will not work for 64 bit types on many platforms.

    You can list all the types you want it to work for by using specializations.
     
    Gianni Mariani, May 9, 2007
    #3
  4. Dominic Connor, Pimp

    Jim Langston Guest

    "Gianni Mariani" <> wrote in message
    news:46423545$0$9105$...
    > Dominic Connor, Pimp wrote:
    >> I've got a bit of code that shows which bits of a variable are 1 or 0
    >> (OK, I'm making assumptions about 8 bit bytes and significance.)
    >>
    >> But what I want to do is only allow this template to be instantiated
    >> for base types, not classes.
    >> I am averse to RTTI for this, but I keep thinking there's a bit of
    >> syntactic sugar that will do it cleanly.
    >> Solutions of the form "classes are bigger than 64 bits so reject them"
    >> don't count :)
    >>
    >> template <typename T> string DumpBits (T x)
    >> {
    >> unsigned int mask=1;


    Are you sure you don't really want
    T mask = 1?
    although I don't think that would work with enums, but what about when T is
    larger than the size of unsigned int?

    >> int i;
    >> string s;
    >>
    >> for ( i= 0; i != sizeof(x)*8; i++, mask *=2)
    >> {
    >> mask & x ? s = "1" + s : s = "0" + s;


    Not that it really matters, but would probably code this line like this:

    s = (mask & x ? "1" : "0") + s;

    Although I've had problems before trying to contcatenate to a string when
    the first element is a char pointer. I guess operator= handles that.

    >> }
    >> return s;
    >> }
    >>

    >
    > That code will not work for 64 bit types on many platforms.
    >
    > You can list all the types you want it to work for by using
    > specializations.


    Why would this not work on some 64 bit implemenations? What is the
    limitation that would prevent it from working? Is it the unsigned int?
     
    Jim Langston, May 10, 2007
    #4
  5. Dominic Connor, Pimp

    Greg Herlihy Guest

    On May 9, 11:01 am, "Dominic Connor, Pimp" <>
    wrote:
    > I've got a bit of code that shows which bits of a variable are 1 or 0
    > (OK, I'm making assumptions about 8 bit bytes and significance.)
    >
    > But what I want to do is only allow this template to be instantiated
    > for base types, not classes.
    > I am averse to RTTI for this, but I keep thinking there's a bit of
    > syntactic sugar that will do it cleanly.
    > Solutions of the form "classes are bigger than 64 bits so reject them"
    > don't count :)
    >
    > template <typename T> string DumpBits (T x)
    > {
    > unsigned int mask=1;
    > int i;
    > string s;
    >
    > for ( i= 0; i != sizeof(x)*8; i++, mask *=2)
    > {
    > mask & x ? s = "1" + s : s = "0" + s;
    > }
    > return s;
    >
    > }


    I would recommend using the TR1 (or boost) type_traits class
    templates; in particular, std::tr1::is_integral<> or
    std::tr1::is_fundamental<> could be used to screen for suitable
    template type arguments.

    Greg
     
    Greg Herlihy, May 10, 2007
    #5
  6. Dominic Connor, Pimp

    Kaz Kylheku Guest

    On May 9, 11:01 am, "Dominic Connor, Pimp" <>
    wrote:
    > I've got a bit of code that shows which bits of a variable are 1 or 0
    > (OK, I'm making assumptions about 8 bit bytes and significance.)
    >
    > But what I want to do is only allow this template to be instantiated
    > for base types, not classes.


    Make the template function private to your module. Instead of exposing
    the template function, expose a set of overloaded functions which use
    the private function for their implementation.

    template <typename T> void dump_bits_impl(T x) { /* ... */ }

    int dump_bits(char x) { dump_bits_impl(x); }
    int dump_bits(int x) { dump_bits_impl(x); }
    int dump_bits(long x) { dump_bits_impl(x); }

    // .. etc: repeat for all supported basic types

    In spite of the trivial repetition, you're still exploiting the
    template as a considerable labor-saving device.

    > I am averse to RTTI for this, but I keep thinking there's a bit of
    > syntactic sugar that will do it cleanly.
    > Solutions of the form "classes are bigger than 64 bits so reject them"
    > don't count :)


    They aren't. How big is class empty {}; on your compiler? :)
     
    Kaz Kylheku, May 10, 2007
    #6
  7. Dominic Connor, Pimp

    James Kanze Guest

    On May 9, 8:01 pm, "Dominic Connor, Pimp" <>
    wrote:
    > I've got a bit of code that shows which bits of a variable are 1 or 0
    > (OK, I'm making assumptions about 8 bit bytes and significance.)


    > But what I want to do is only allow this template to be instantiated
    > for base types, not classes.
    > I am averse to RTTI for this, but I keep thinking there's a bit of
    > syntactic sugar that will do it cleanly.
    > Solutions of the form "classes are bigger than 64 bits so reject them"
    > don't count :)


    > template <typename T> string DumpBits (T x)
    > {
    > unsigned int mask=1;
    > int i;
    > string s;
    >
    > for ( i= 0; i != sizeof(x)*8; i++, mask *=2)
    > {
    > mask & x ? s = "1" + s : s = "0" + s;
    > }
    > return s;
    >
    > }


    For starters, why not write the function something like:

    template< typename T >
    std::string
    dumpBits( T value )
    {
    std::string result ;
    while ( result.size() < sizeof( T ) * CHAR_BIT ) {
    result += (value & 1 == 0) ? '0' : '1' ;
    // or: result += (value & 1) + '0' ;
    value >>= 1 ;
    }
    std::reverse( result.begin(), result.end() ) ;
    return result ;
    }

    This will reject anything for which & or >> isn't defined, which
    means anything that isn't either an integral type or designed to
    behave like an integral type. Most likely, that's sufficient.
    (Of course, the error message isn't very pretty. But then, is
    it ever, when you use templates?)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 10, 2007
    #7
    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.
Similar Threads
  1. Replies:
    0
    Views:
    454
  2. Marian Schedenig

    HP LaserJet rejects print jobs

    Marian Schedenig, Aug 9, 2007, in forum: Java
    Replies:
    0
    Views:
    436
    Marian Schedenig
    Aug 9, 2007
  3. Qu0ll
    Replies:
    42
    Views:
    1,277
    Thufir Hawat
    Apr 13, 2009
  4. helveticus

    Server rejects template script request

    helveticus, Jul 1, 2009, in forum: ASP .Net
    Replies:
    1
    Views:
    1,116
    helveticus
    Jul 2, 2009
  5. Jim
    Replies:
    7
    Views:
    115
    Thomas 'PointedEars' Lahn
    Nov 15, 2007
Loading...

Share This Page