Structure layout

Discussion in 'C++' started by kelvSYC, Jun 4, 2005.

  1. kelvSYC

    kelvSYC Guest

    As you might know, std::fwrite only works on POD classes (or in the
    very least, I am advised to use this only on POD classes...). I have
    this POD class that I want to add methods, and thus have to replace
    parts of my code where I have to call std::fwrite.

    For example, I have

    struct foo {
    int a;
    char b;
    };

    // ...
    foo f;
    FILE* file;
    std::fwrite (&f, 1, sizeof(f), file);
    // ...

    If I add a method to foo, how would I change the code snippet?

    --
    I am only a mirage.
    kelvSYC, Jun 4, 2005
    #1
    1. Advertising

  2. kelvSYC

    Ian Guest

    kelvSYC wrote:
    > As you might know, std::fwrite only works on POD classes (or in the
    > very least, I am advised to use this only on POD classes...). I have
    > this POD class that I want to add methods, and thus have to replace
    > parts of my code where I have to call std::fwrite.
    >
    > For example, I have
    >
    > struct foo {
    > int a;
    > char b;
    > };
    >
    > // ...
    > foo f;
    > FILE* file;
    > std::fwrite (&f, 1, sizeof(f), file);
    > // ...
    >
    > If I add a method to foo, how would I change the code snippet?
    >

    As long as there are no virtual methods or non pod members, it should
    still work. But I'd give it proper streaming operators.

    friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );
    friend std::istream& operator>>( std::istream& out, foo& f );

    Ian
    Ian, Jun 4, 2005
    #2
    1. Advertising

  3. kelvSYC

    Rapscallion Guest

    Ian wrote:
    > kelvSYC wrote:
    > > foo f;
    > > FILE* file;
    > > std::fwrite (&f, 1, sizeof(f), file);

    ....
    > As long as there are no virtual methods or non pod members, it should
    > still work. But I'd give it proper streaming operators.
    >
    > friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );


    .... which probably isn't quite the same as
    fwrite (&f, sizeof(f), 1, file);
    Rapscallion, Jun 4, 2005
    #3
  4. kelvSYC

    Ian Guest

    Rapscallion wrote:
    > Ian wrote:
    >
    >>kelvSYC wrote:
    >>
    >>>foo f;
    >>>FILE* file;
    >>>std::fwrite (&f, 1, sizeof(f), file);

    >
    > ...
    >
    >>As long as there are no virtual methods or non pod members, it should
    >>still work. But I'd give it proper streaming operators.
    >>
    >>friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );

    >
    >
    > ... which probably isn't quite the same as
    > fwrite (&f, sizeof(f), 1, file);
    >

    True, that's why I suggested complimentary operators!

    Ian
    Ian, Jun 4, 2005
    #4
  5. kelvSYC

    Guest

    If you're going to define streaming operators for 'foo', there is no
    reason not to include non-pod members. I'm certain there is code
    available to stream STL containers (otherwise you can write it). And if
    you have your own value-semantic types, you should always provide
    streaming operators for them. /david
    , Jun 4, 2005
    #5
  6. kelvSYC

    kelvSYC Guest

    In article <>, Ian
    <> wrote:

    > kelvSYC wrote:
    > > As you might know, std::fwrite only works on POD classes (or in the
    > > very least, I am advised to use this only on POD classes...). I have
    > > this POD class that I want to add methods, and thus have to replace
    > > parts of my code where I have to call std::fwrite.
    > >
    > > For example, I have
    > >
    > > struct foo {
    > > int a;
    > > char b;
    > > };
    > >
    > > // ...
    > > foo f;
    > > FILE* file;
    > > std::fwrite (&f, 1, sizeof(f), file);
    > > // ...
    > >
    > > If I add a method to foo, how would I change the code snippet?
    > >

    > As long as there are no virtual methods or non pod members, it should
    > still work.


    I see. Adding a nonvirtual member function would not affect its
    pod-ness.

    So what would I do if I had something like

    struct bar {
    int a;
    char b[32];
    };

    and I wanted to add a constructor/non-pod member/virtual member
    function/etc. to make it non-pod? How would I change the code snippet
    above?

    > But I'd give it proper streaming operators.
    >
    > friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );
    > friend std::istream& operator>>( std::istream& out, foo& f );


    I thought streaming operators were meant for text input and output
    only. std::fwrite is binary output.

    --
    I am only a mirage.
    kelvSYC, Jun 4, 2005
    #6
  7. kelvSYC

    Guest

    kelvSYC wrote:
    > In article <>, Ian
    > <> wrote:
    >
    > > kelvSYC wrote:
    > > > As you might know, std::fwrite only works on POD classes (or in the
    > > > very least, I am advised to use this only on POD classes...). I have
    > > > this POD class that I want to add methods, and thus have to replace
    > > > parts of my code where I have to call std::fwrite.
    > > >
    > > > For example, I have
    > > >
    > > > struct foo {
    > > > int a;
    > > > char b;
    > > > };
    > > >
    > > > // ...
    > > > foo f;
    > > > FILE* file;
    > > > std::fwrite (&f, 1, sizeof(f), file);
    > > > // ...
    > > >
    > > > If I add a method to foo, how would I change the code snippet?
    > > >

    > > As long as there are no virtual methods or non pod members, it should
    > > still work.

    >
    > I see. Adding a nonvirtual member function would not affect its
    > pod-ness.
    >
    > So what would I do if I had something like
    >
    > struct bar {
    > int a;
    > char b[32];
    > };
    >
    > and I wanted to add a constructor/non-pod member/virtual member
    > function/etc. to make it non-pod? How would I change the code snippet
    > above?


    For example,

    struct bar {
    int a;
    char b[32];

    std::vector<int> v;

    private:
    // not implemented
    bar(const bar&);
    bar& operator=(const bar&);

    public:
    bar() : a(0) { b[0] = 0; }
    ~bar();

    virtual std::eek:stream& streamOut(std::eek:stream& stream);
    };

    But I would not advise this. Make it a proper class.

    > > But I'd give it proper streaming operators.
    > >
    > > friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );
    > > friend std::istream& operator>>( std::istream& out, foo& f );

    >
    > I thought streaming operators were meant for text input and output
    > only. std::fwrite is binary output.


    No. There is no reason why the istream cannot represent a binary
    stream. Indeed, it all depends on how the underlying streambuf is
    implemented. It is easy to imagine something like

    my_FwriteStreamBuf buf("filename"); // implemented with 'fwrite'
    std::eek:stream stream(&buf);
    stream << object << std::endl;

    /david
    , Jun 4, 2005
    #7
  8. kelvSYC

    Peter Julian Guest

    "kelvSYC" <> wrote in message
    news:040620050904364520%...
    > In article <>, Ian
    > <> wrote:
    >

    <snip>
    > > >

    > > As long as there are no virtual methods or non pod members, it should
    > > still work.

    >
    > I see. Adding a nonvirtual member function would not affect its
    > pod-ness.
    >
    > So what would I do if I had something like
    >
    > struct bar {
    > int a;
    > char b[32];
    > };
    >
    > and I wanted to add a constructor/non-pod member/virtual member
    > function/etc. to make it non-pod? How would I change the code snippet
    > above?
    >
    > > But I'd give it proper streaming operators.
    > >
    > > friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );
    > > friend std::istream& operator>>( std::istream& out, foo& f );

    >
    > I thought streaming operators were meant for text input and output
    > only. std::fwrite is binary output.


    No sir, those operators are binary.

    As far as a non-pod class is concerned, why not develop a Bar class and a
    container to serialize the data. A std::string is implemented instead of a
    fixed char array:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <vector>
    #include <iterator>
    #include <stdexcept>

    class Bar
    {
    int m_n;
    std::string m_s;
    public:
    Bar(int n, std::string s) : m_n(n), m_s(s) { }
    ~Bar() { }

    friend std::eek:stream& operator<<( std::eek:stream& os, const Bar& r_bar_ )
    {
    os << r_bar_.m_n << " ";;
    os << r_bar_.m_s;
    return os;
    }

    friend std::istream& operator>>( std::istream& is, Bar& r_bar )
    {
    is >> r_bar.m_n >> r_bar.m_s;
    return is;
    }
    }; // class Bar

    class BarContainer
    {
    std::string s_filename;
    std::vector<Bar> v_bar;
    public:
    BarContainer(std::string s) : v_bar(), s_filename(s) { }
    ~BarContainer() { }

    // member functions
    void push_back(const Bar& r_bar_)
    {
    v_bar.push_back(r_bar_);
    }

    void write() const
    {
    std::eek:fstream ofs;
    ofs.open(s_filename.c_str());
    if (!ofs)
    {
    throw std::exception("while opening file for output");
    }

    std::eek:stream& os = ofs;
    std::copy( v_bar.begin(),
    v_bar.end(),
    std::eek:stream_iterator<Bar>(os, "\n") );
    ofs.close();
    std::cout << "\nBarContainer::write() ... file ";
    std::cout << s_filename << " created successfully.\n";
    } // write()

    void display() const
    {
    std::cout << "BarContainer::display() [ size = ";
    std::cout << v_bar.size() << " ]\n";

    std::eek:stream& r_os = std::cout;
    std::copy( v_bar.begin(),
    v_bar.end(),
    std::eek:stream_iterator<Bar>(r_os, "\n") );
    /*
    // the above code is simpler than...
    typedef std::vector<Bar>::iterator VITER;
    VITER viter = v_bar.begin();
    for (viter; viter != v_bar.end(); ++viter)
    {
    std::cout << *viter << "\n";
    }
    */
    } // display()

    }; // class Bar

    int main()
    {
    // initialize Container with filename
    BarContainer bc("data.dat");

    // load Container
    bc.push_back(Bar(0, "string_zero"));
    bc.push_back(Bar(1, "string_one"));
    bc.push_back(Bar(2, "string_two"));
    bc.push_back(Bar(3, "string_three"));
    bc.push_back(Bar(4, "string_four"));

    // display its contents
    bc.display();

    try
    {
    // serialize Container to file
    bc.write();
    }
    catch (const std::exception& e)
    {
    std::cerr << "Error !\n";
    std::cerr << e.what() << "\n";
    }

    return 0;
    } // main(...)

    /*
    BarContainer::display() [ size = 5 ]
    0 string_zero
    1 string_one
    2 string_two
    3 string_three
    4 string_four

    BarContainer::write() ... file data.dat created successfully.

    */
    Peter Julian, Jun 4, 2005
    #8
  9. kelvSYC

    kelvSYC Guest

    > > > But I'd give it proper streaming operators.
    > > >
    > > > friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );
    > > > friend std::istream& operator>>( std::istream& out, foo& f );

    > >
    > > I thought streaming operators were meant for text input and output
    > > only. std::fwrite is binary output.

    >
    > No. There is no reason why the istream cannot represent a binary
    > stream. Indeed, it all depends on how the underlying streambuf is
    > implemented. It is easy to imagine something like
    >
    > my_FwriteStreamBuf buf("filename"); // implemented with 'fwrite'
    > std::eek:stream stream(&buf);
    > stream << object << std::endl;


    Since I'm not of good enough ability to write a streambuf that would be
    implemented with fwrite (I don't fully understand what I have to do in
    order to write one), where could I find one?

    --
    I am only a mirage.
    kelvSYC, Jun 5, 2005
    #9
  10. kelvSYC

    Guest

    kelvSYC wrote:
    > > > > But I'd give it proper streaming operators.
    > > > >
    > > > > friend std::eek:stream& operator<<( std::eek:stream& out, const foo& f );
    > > > > friend std::istream& operator>>( std::istream& out, foo& f );
    > > >
    > > > I thought streaming operators were meant for text input and output
    > > > only. std::fwrite is binary output.

    > >
    > > No. There is no reason why the istream cannot represent a binary
    > > stream. Indeed, it all depends on how the underlying streambuf is
    > > implemented. It is easy to imagine something like
    > >
    > > my_FwriteStreamBuf buf("filename"); // implemented with 'fwrite'
    > > std::eek:stream stream(&buf);
    > > stream << object << std::endl;

    >
    > Since I'm not of good enough ability to write a streambuf that would be
    > implemented with fwrite (I don't fully understand what I have to do in
    > order to write one), where could I find one?


    You can use 'std::fstream'. Construct or 'open' an 'std::fstream'
    object with the 'ios_base::binary' open mode. /david
    , Jun 5, 2005
    #10
  11. kelvSYC

    kelvSYC Guest

    In article <>,
    <> wrote:

    > kelvSYC wrote:
    > > Since I'm not of good enough ability to write a streambuf that would be
    > > implemented with fwrite (I don't fully understand what I have to do in
    > > order to write one), where could I find one?

    >
    > You can use 'std::fstream'. Construct or 'open' an 'std::fstream'
    > object with the 'ios_base::binary' open mode. /david


    I'm actually looking for binary (ie. not character-based) output, so,
    seeing how everyone advises not to (ab)use write() for unformatted
    output, I'd need to find a stream(buf) that would do this.

    --
    I am only a mirage.
    kelvSYC, Jun 5, 2005
    #11
  12. kelvSYC

    Guest

    kelvSYC wrote:
    > In article <>,
    > <> wrote:
    >
    > > kelvSYC wrote:
    > > > Since I'm not of good enough ability to write a streambuf that would be
    > > > implemented with fwrite (I don't fully understand what I have to do in
    > > > order to write one), where could I find one?

    > >
    > > You can use 'std::fstream'. Construct or 'open' an 'std::fstream'
    > > object with the 'ios_base::binary' open mode. /david

    >
    > I'm actually looking for binary (ie. not character-based) output, so,
    > seeing how everyone advises not to (ab)use write() for unformatted
    > output, I'd need to find a stream(buf) that would do this.


    Maybe I'm not understanding you. You either want something like this:

    my_Pod pod;
    //...
    std::fstream ofs(filename, ios_base::binary);
    ofs.write((const char *)&my_pod, sizeof pod);

    or this (to show use of std::streambuf)

    my_Pod pod;
    //...
    std::fstream ofs(filename, ios_base::binary);
    std::streambuf *buf = ofs.rdbuf();
    buf->sputn((const char *)&pod, sizeof pod);
    buf->pubsync();

    or this

    std::eek:stream& operator<<(std::eek:stream& stream, const my_Pod& pod)
    {
    // one of the above implementations, probably the first
    return stream;
    }

    /david
    , Jun 5, 2005
    #12
    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. Rick Spiewak
    Replies:
    3
    Views:
    3,135
    Rick Spiewak
    Aug 26, 2003
  2. RobertH
    Replies:
    1
    Views:
    711
    Steve C. Orr [MVP, MCSD]
    Nov 4, 2003
  3. NWx
    Replies:
    4
    Views:
    2,951
    Kevin Spencer
    Feb 19, 2004
  4. Eric
    Replies:
    4
    Views:
    700
    clintonG
    Dec 24, 2004
  5. Replies:
    1
    Views:
    564
    John Timney \(MVP\)
    Jun 19, 2006
Loading...

Share This Page