implementation details

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • forums_mp

    implementation details

    After reading a few texts - nameley koeing/moo and eckel - I decided
    to investigating the importance of templates. Of course there's no
    substitute for practice so I figured I try a simple program.

    That said I'm interested in suggestions for improvement on the
    template class (be gracious i'm slowly coming up to speed in ++ :))
    but more importantly I have a few questions.
    For starters, in an ideal world each call to Store should be followed
    by a subsequent Retrieve. If however, Store was called twice before a
    Retrieve then I'd like to implement some sort of overrun check. I
    suspect this could be handled with an overrun_count that'll get
    incremented in Store and decremented in Retrieve or (implementation
    help here)???

    Conceptually I understand teh copy constructor and/or assignment
    operator (the heavy stuff but need to revisit) but I'm curious to see
    an implementation of the assignment operator that'll compare two
    buffers and a copy constructor that'll do just that. Copy an new
    object based on exisitng.

    The code


    // template.h
    enum BOOLEAN { FALSE = 0,
    TRUE};

    template <class T>
    class BUFFER
    {
    public:

    BUFFER();
    ~BUFFER();
    void Store(unsigned char const* buffer);
    BOOLEAN Retrieve(T& data);
    // T Retrieve(T& data); would this be more prudent ??
    int Elements_Stored () const;
    int Elements_Retrie ved() const;

    private:

    static const int SIZE = 2;
    T msg [ SIZE ];

    unsigned int store_count;
    unsigned int store_index;
    unsigned int retrieve_count;

    // override compiler defaults
    BUFFER(BUFFER<T >& buffer); // Copy construtor.
    void operator= (BUFFER<T>& rhs); // Assignment operator


    };

    // Constructor
    template<class T>
    BUFFER<T>::BUFF ER()
    : store_count(0), retrieve_count( 0), store_index(1)
    {
    memset( msg, 0, SIZE * sizeof(T));
    }

    // Destructor
    template<class T>
    BUFFER<T>::~BUF FER()
    {
    }

    // store two items. the current and the previous
    template<class T>
    void BUFFER<T>::Stor e( unsigned char const* buffer)
    {
    store_index ^= 1;
    // supposidely memcpy is bad news but std::copy benchmarked is slow
    // when compared to memcpy
    memcpy( &msg[store_index], buffer, sizeof(T));
    store_count++; // increment the message stored count
    }

    // retrieve the most CURRENT item at ALL times
    template<class T>
    BOOLEAN BUFFER<T>::Retr ieve(T& data)
    {
    if (store_count > 0) // here only to ensure the Retrieve never
    // gets called the VERY FIRST TIME before the
    Store
    {
    memcpy( &data, &msg[store_index], sizeof(T));
    retrieve_count+ +;
    return TRUE;
    }
    else
    {
    return FALSE;
    }
    }

    // returns number of elements stored.
    template<class T>
    int BUFFER<T>::Elem ents_Stored() const
    {
    return store_count;
    }

    // returns number of elements retrieved.
    template<class T>
    int BUFFER<T>::Elem ents_Retrieved( ) const
    {
    return retrieve_count;
    }


    // template.cpp file

    #define MAX_MSG_SIZE 4 // avoid preprocessor macro in a ++
    environment

    enum BOGUS_MSG { msg1Msg,
    msg2Msg };

    // For simplicity make bit fields 8 deep
    struct MSG1
    {
    unsigned int jdx1 : 8;
    unsigned int jdx2 : 8;
    unsigned int jdx3 : 8;
    unsigned int jdx4 : 8;
    };

    struct MSG2
    {
    unsigned int idx1 : 8;
    unsigned int idx2 : 8;
    unsigned int idx3 : 8;
    unsigned int idx4 : 8;
    };


    int main ( void )
    {

    BOGUS_MSG msgType;
    MSG1 localMsg;
    BOOLEAN success;

    // Done once at initilization.
    BUFFER<MSG1> msg1;
    BUFFER<MSG2> msg2;

    unsigned char buffer [ MAX_MSG_SIZE ] = { 12, 1, 15, 5 };
    memset(&localMs g, 0, sizeof(MSG1)); // no real reason since
    // I'll overwrite
    localMsg

    std::cout << " ----- Before call to Store and Retrieve ---- "
    << std::endl;
    std::cout << "MSG1 - jdx1 = " << localMsg.jdx1 << std::endl;
    std::cout << "MSG1 - jdx2 = "<< localMsg.jdx2 << std::endl;
    std::cout << "MSG1 - jdx3 = " << localMsg.jdx3 << std::endl;
    std::cout << "MSG1 - jdx4 = " << localMsg.jdx4 << std::endl;

    msgType = msg1Msg;

    switch ( msgType )
    {
    case msg1Msg:
    msg1.Store ( buffer );
    break;
    case msg2Msg:
    msg2.Store ( buffer );
    break;
    default:
    std::cout << " bad msg " << std::endl;
    break;
    }

    // later lets Retrieve a message
    success = msg1.Retrieve(l ocalMsg); // retrieve the message
    if ( success )
    {
    std::cout << " ----- After call to Store and Retrieve ---- "
    << std::endl;
    std::cout << "MSG1 - jdx1 = " << localMsg.jdx1 << std::endl;
    std::cout << "MSG1 - jdx2 = "<< localMsg.jdx2 << std::endl;
    std::cout << "MSG1 - jdx3 = " << localMsg.jdx3 << std::endl;
    std::cout << "MSG1 - jdx4 = " << localMsg.jdx4 << std::endl;
    }

    // Call msg1.Store message a couple times
    // Call msg2.Store
    msg1.Store ( buffer );
    msg1.Store ( buffer );
    msg2.Store ( buffer );

    // Print out the index of how many times msg1(should equate to 3)
    stored
    // Print out the index of how many times msg1(should equate to 1)
    stored
    std::cout << " --------------------------------------------- "
    << std::endl;
    std::cout << "Times called -- MSG1: "
    << msg1.Elements_S tored()
    << std::endl;

    std::cout << " --------------------------------------------- "
    << std::endl;
    std::cout << "Times called -- MSG2: "
    << msg2.Elements_S tored()
    << std::endl;
    std::cout << " --------------------------------------------- "
    << std::endl;

    return EXIT_SUCCESS;
    }//// end


    I'll modify said code to move into the container realm later.

    Thanks in advance
  • Davlet Panech

    #2
    Re: implementation details


    "forums_mp" <forums_mp@hotm ail.com> wrote in message
    news:ee300167.0 310250833.54e56 a8e@posting.goo gle.com...[color=blue]
    > After reading a few texts - nameley koeing/moo and eckel - I decided
    > to investigating the importance of templates. Of course there's no
    > substitute for practice so I figured I try a simple program.
    >
    > That said I'm interested in suggestions for improvement on the
    > template class (be gracious i'm slowly coming up to speed in ++ :))
    > but more importantly I have a few questions.
    > For starters, in an ideal world each call to Store should be followed
    > by a subsequent Retrieve. If however, Store was called twice before a
    > Retrieve then I'd like to implement some sort of overrun check. I
    > suspect this could be handled with an overrun_count that'll get
    > incremented in Store and decremented in Retrieve or (implementation
    > help here)???
    >
    > Conceptually I understand teh copy constructor and/or assignment
    > operator (the heavy stuff but need to revisit) but I'm curious to see
    > an implementation of the assignment operator that'll compare two
    > buffers and a copy constructor that'll do just that. Copy an new
    > object based on exisitng.
    >
    > The code[/color]

    Perhaps you should state what your buffer class is supposed to do. As far as
    I can tell it's trying to convert objects of arbitrary types to char arrays.
    This will only work for POD types (ints, pointers, structs w/o virtual
    members, constructors, etc.). Why don't you try to implement a class that
    actually makes sense and is a bit more useful, like a stack of a fixed size.

    Anyway, some observations:
    - "template.h " is too vague a file name. ".h" is usually used with C
    headers. I suggest <ClassName>.h pp instead.
    - There is a perfectly good boolean type in C++ already (bool/true/false).
    - Since your destructor doesn't do anything, you don't have to declare and
    define it.
    - Copy ctor takes its argument by *const reference*.
    - Assignment operator takes its argument by *const reference* and returns a
    *non-const reference" to current object ("return *this;").
    - I don't think you need a copy ctor and assignment op in your class at all.
    Although I'm not 100% sure as it's a little hard to understand what you are
    trying to accomplish. If you don't have members that require explicit
    allocation/deallocation, you usually don't need to write copy functions or
    the destructor.

    D.


    Comment

    • forums_mp

      #3
      Re: implementation details

      >[color=blue]
      > Perhaps you should state what your buffer class is supposed to do. As far as
      > I can tell it's trying to convert objects of arbitrary types to char arrays.
      > This will only work for POD types (ints, pointers, structs w/o virtual
      > members, constructors, etc.). Why don't you try to implement a class that
      > actually makes sense and is a bit more useful, like a stack of a fixed size.[/color]

      Makes 'sense' in what respect? In that regard I'm curious to see how
      a stack of a fixed size will be oso differnt when compared to the
      simple implementation which I assumed you've 'looked' at. Of course,
      realize i'm new to this but in the end all i'm trying to do is
      implement a store function that when called will store the most
      current and previous message ( a buffer two deep). A retrieve
      fucntion when called will return the latest.
      [color=blue]
      >
      > Anyway, some observations:
      > - "template.h " is too vague a file name. ".h" is usually used with C
      > headers. I suggest <ClassName>.h pp instead.[/color]
      I've seen this 'hpp' bit but i'll investigate what that's all about.
      In essense, whats the net gain. Is this some new form of 'header'?
      [color=blue]
      > - There is a perfectly good boolean type in C++ already (bool/true/false).
      > - Since your destructor doesn't do anything, you don't have to declare and
      > define it.[/color]
      agreed on two counts.[color=blue]
      > - Copy ctor takes its argument by *const reference*.[/color]
      Yikes, missing the const[color=blue]
      > - Assignment operator takes its argument by *const reference* and returns a
      > *non-const reference" to current object ("return *this;").[/color]
      ditto[color=blue]
      > - I don't think you need a copy ctor and assignment op in your class at all.
      > Although I'm not 100% sure as it's a little hard to understand what you are
      > trying to accomplish. If you don't have members that require explicit
      > allocation/deallocation, you usually don't need to write copy functions or
      > the destructor.[/color]
      and I dont require explicit alloc/dealloc. got it!! in light of the
      copy cstructor i thought well if I had.

      BUFFER<MSG1 > b2;

      // later
      BUFFER<MSG1 > b3 = b2; // cpystructor would come in handy here?[color=blue]
      > D.[/color]

      Comment

      • Davlet Panech

        #4
        Re: implementation details


        "forums_mp" <forums_mp@hotm ail.com> wrote in message
        news:ee300167.0 310260700.31684 83b@posting.goo gle.com...[color=blue][color=green]
        > >
        > > Perhaps you should state what your buffer class is supposed to do. As[/color][/color]
        far as[color=blue][color=green]
        > > I can tell it's trying to convert objects of arbitrary types to char[/color][/color]
        arrays.[color=blue][color=green]
        > > This will only work for POD types (ints, pointers, structs w/o virtual
        > > members, constructors, etc.). Why don't you try to implement a class[/color][/color]
        that[color=blue][color=green]
        > > actually makes sense and is a bit more useful, like a stack of a fixed[/color][/color]
        size.[color=blue]
        >
        > Makes 'sense' in what respect? In that regard I'm curious to see how
        > a stack of a fixed size will be oso differnt when compared to the
        > simple implementation which I assumed you've 'looked' at. Of course,
        > realize i'm new to this but in the end all i'm trying to do is
        > implement a store function that when called will store the most
        > current and previous message ( a buffer two deep). A retrieve
        > fucntion when called will return the latest.[/color]

        What I'm saying is you can't do "byte copying" (memcpy(), or equivalent)
        with most classes. You should use assignment or copy constrution instead,
        instead of "memcpy (&array[index], &a, sizeof (a))", do "array[index] = a".
        [color=blue]
        >[color=green]
        > >
        > > Anyway, some observations:
        > > - "template.h " is too vague a file name. ".h" is usually used with C
        > > headers. I suggest <ClassName>.h pp instead.[/color]
        > I've seen this 'hpp' bit but i'll investigate what that's all about.
        > In essense, whats the net gain. Is this some new form of 'header'?[/color]

        It's just a common convention; compilers don't care about file names.
        [color=blue][color=green]
        > > - I don't think you need a copy ctor and assignment op in your class at[/color][/color]
        all.[color=blue][color=green]
        > > Although I'm not 100% sure as it's a little hard to understand what you[/color][/color]
        are[color=blue][color=green]
        > > trying to accomplish. If you don't have members that require explicit
        > > allocation/deallocation, you usually don't need to write copy functions[/color][/color]
        or[color=blue][color=green]
        > > the destructor.[/color]
        > and I dont require explicit alloc/dealloc. got it!! in light of the
        > copy cstructor i thought well if I had.
        >
        > BUFFER<MSG1 > b2;
        >
        > // later
        > BUFFER<MSG1 > b3 = b2; // cpystructor would come in handy here?[/color]

        If you don't write a copy ctor/assignment, the compiler will generate one
        that copies every member of the source object to the corresponding members
        of the destination object. This is good enough for your case.

        In other words,
        BUFFER<MSG1 > b3 = b2;
        will do what you expect even if you don't write copy functions yourself.

        D.


        Comment

        Working...