Reference to temporary

Discussion in 'C++' started by Dave, Nov 5, 2003.

  1. Dave

    Dave Guest

    Hello all,

    The code below is not legal (problem with the foo_t initializer list)
    because:

    "A reference that is not to 'const' cannot be bound to a non-lvalue"

    How can I best achieve an effect similar to what this code attempts?

    Thanks,
    Dave

    class bar_t
    {
    };

    class foo_t
    {
    public:
    foo_t(): ref(bar_t()) {}

    private:
    bar_t &ref;
    };

    void foo()
    {
    foo_t a;
    }

    int main()
    {
    foo();

    return 0;
    }
    Dave, Nov 5, 2003
    #1
    1. Advertising

  2. Dave

    Ron Natalie Guest

    "Dave" <> wrote in message news:...
    > Hello all,
    >
    > The code below is not legal (problem with the foo_t initializer list)
    > because:
    >
    > "A reference that is not to 'const' cannot be bound to a non-lvalue"
    >
    > How can I best achieve an effect similar to what this code attempts?
    >


    Use a const reference?
    Ron Natalie, Nov 6, 2003
    #2
    1. Advertising

  3. Dave wrote in news::

    > Hello all,
    >
    > The code below is not legal (problem with the foo_t initializer list)
    > because:
    >
    > "A reference that is not to 'const' cannot be bound to a non-lvalue"
    >
    > How can I best achieve an effect similar to what this code attempts?
    >
    > Thanks,
    > Dave
    >
    > class bar_t
    > {
    > };
    >
    > class foo_t
    > {
    > public:
    > foo_t(): ref(bar_t()) {}
    >
    > private:
    > bar_t &ref;
    > };


    You would have to tell us what is wrong with:

    class foo_t
    {
    public:
    foo_t() {}

    private:
    bar_t ref;
    };

    I.e. what problem you need to solve.

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Nov 6, 2003
    #3
  4. Dave wrote:
    > ...
    > The code below is not legal (problem with the foo_t initializer list)
    > because:
    >
    > "A reference that is not to 'const' cannot be bound to a non-lvalue"
    >
    > How can I best achieve an effect similar to what this code attempts?
    >
    >
    > class bar_t
    > {
    > };
    >
    > class foo_t
    > {
    > public:
    > foo_t(): ref(bar_t()) {}
    >
    > private:
    > bar_t &ref;
    > };
    >
    > void foo()
    > {
    > foo_t a;
    > }
    >
    > int main()
    > {
    > foo();
    >
    > return 0;
    > }
    > ...


    You can't do it this way. It you need a valid reference, which is a
    member of some class, you need a valid lvalue object (i.e. a
    non-temporary) to initialize it with. The object's lifetime should be at
    least as long as the lifetime of the reference.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Nov 6, 2003
    #4
  5. Ron Natalie wrote:
    >>...
    >> The code below is not legal (problem with the foo_t initializer list)
    >> because:
    >>
    >> "A reference that is not to 'const' cannot be bound to a non-lvalue"
    >>
    >> How can I best achieve an effect similar to what this code attempts?
    >>

    >
    > Use a const reference?
    > ...


    That will replace one problem with another. The code will compile, but
    reference member will only remain valid until the constructor exits.
    After that the reference is no longer valid. Something tells me that
    that's not what OP intended to achieve.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Nov 6, 2003
    #5
  6. Dave

    Cy Edmunds Guest

    "Dave" <> wrote in message
    news:...
    > Hello all,
    >
    > The code below is not legal (problem with the foo_t initializer list)
    > because:
    >
    > "A reference that is not to 'const' cannot be bound to a non-lvalue"
    >
    > How can I best achieve an effect similar to what this code attempts?


    [snip]

    Just change the reference to an object:

    class foo_t
    {
    private:
    bar_t;
    };
    Cy Edmunds, Nov 6, 2003
    #6
  7. Dave

    Dave Guest

    Hello all,

    Well, I think I need to elaborate upon my previous post. My simplified
    version of things did not provide enough context...

    I am maintaining a very poor existing code base (isn't it the bane of all
    our existences???). There is a class which contains as a data member an
    ofstream object which is used for logging. This object is bound to a log
    file upon object construction, so the stream's ready to write to by the time
    we start doing any real work. So far so good... Where it gets messy is
    that there is also a member function SetStream() to change the stream
    dynamically. So, we may log to the initial stream for awhile, and then
    decide to start logging to another stream. Seems like a reasonable thing to
    want to do. However, SetStream() takes an ofstream parameter by value and
    then assigns it to the member ofstream object. There are two problems
    here - ofstream has neither a copy constructor nor an assignment operator,
    so passing it as a parameter and assigning it are both illegal! This should
    have never compiled, but we had a poor compiler (VC++ 6.0) and it was let
    through. Now that we've upgraded to a more compliant compiler, the error is
    finally getting caught.

    So, I need to figure out a way to update this stream data member
    dynamically. I have considered changing the data member from ofstream to
    ofstream*, but there's a problem. The initial stream (upon object
    construction) would have to be dynamically allocated, which means it would
    have to be deallocated in the destructor. However, the client code that
    uses this class passes non-dynamically allocated ofstream objects when it
    calls SetStream(). So, we can start passing pointers rather than the
    objects themselves, but the pointer can't be deallocated by the
    destructor... I guess I could use a flag to mark whether the pointer points
    to the orignal dynamically-allocated object or not, but there's got to be a
    more elegant way...

    My earlier attempt (in my original post) at trying to find a way to solve
    this with reference members was off in la la land because an initializer
    list can't initialize a reference member if the class in question has no
    copy constructor. If this makes no sense, don't worry about it; there's no
    need to go back and look at the original post. It was headed in the wrong
    direction...

    Thanks again,
    Dave
    Dave, Nov 6, 2003
    #7
  8. Dave

    Cy Edmunds Guest

    "Dave" <> wrote in message
    news:...
    > Hello all,
    >
    > Well, I think I need to elaborate upon my previous post. My simplified
    > version of things did not provide enough context...
    >
    > I am maintaining a very poor existing code base (isn't it the bane of all
    > our existences???). There is a class which contains as a data member an
    > ofstream object which is used for logging. This object is bound to a log
    > file upon object construction, so the stream's ready to write to by the

    time
    > we start doing any real work. So far so good... Where it gets messy is
    > that there is also a member function SetStream() to change the stream
    > dynamically. So, we may log to the initial stream for awhile, and then
    > decide to start logging to another stream. Seems like a reasonable thing

    to
    > want to do. However, SetStream() takes an ofstream parameter by value and
    > then assigns it to the member ofstream object. There are two problems
    > here - ofstream has neither a copy constructor nor an assignment operator,
    > so passing it as a parameter and assigning it are both illegal! This

    should
    > have never compiled, but we had a poor compiler (VC++ 6.0) and it was let
    > through. Now that we've upgraded to a more compliant compiler, the error

    is
    > finally getting caught.
    >
    > So, I need to figure out a way to update this stream data member
    > dynamically. I have considered changing the data member from ofstream to
    > ofstream*, but there's a problem. The initial stream (upon object
    > construction) would have to be dynamically allocated,


    Why?

    std::eek:stream *m_pstr;
    void SetStream(std::eek:stream &new_stream) {m_pstr = &new_stream;} // pass by
    reference and store the address

    Of course the life of the stream has to be longer than the life of the
    object, but that can't be helped. To use it:

    *m_pstr << "whatever";

    which means it would
    > have to be deallocated in the destructor. However, the client code that
    > uses this class passes non-dynamically allocated ofstream objects when it
    > calls SetStream(). So, we can start passing pointers rather than the
    > objects themselves, but the pointer can't be deallocated by the
    > destructor... I guess I could use a flag to mark whether the pointer

    points
    > to the orignal dynamically-allocated object or not, but there's got to be

    a
    > more elegant way...
    >
    > My earlier attempt (in my original post) at trying to find a way to solve
    > this with reference members was off in la la land because an initializer
    > list can't initialize a reference member if the class in question has no
    > copy constructor. If this makes no sense, don't worry about it; there's

    no
    > need to go back and look at the original post. It was headed in the wrong
    > direction...
    >
    > Thanks again,
    > Dave
    >




    --
    Cy
    http://home.rochester.rr.com/cyhome/
    Cy Edmunds, Nov 6, 2003
    #8
  9. Dave

    Dave Guest

    "Cy Edmunds" <> wrote in message
    news:eyvqb.61692$...
    > "Dave" <> wrote in message
    > news:...
    > > Hello all,
    > >
    > > Well, I think I need to elaborate upon my previous post. My simplified
    > > version of things did not provide enough context...
    > >
    > > I am maintaining a very poor existing code base (isn't it the bane of

    all
    > > our existences???). There is a class which contains as a data member an
    > > ofstream object which is used for logging. This object is bound to a

    log
    > > file upon object construction, so the stream's ready to write to by the

    > time
    > > we start doing any real work. So far so good... Where it gets messy is
    > > that there is also a member function SetStream() to change the stream
    > > dynamically. So, we may log to the initial stream for awhile, and then
    > > decide to start logging to another stream. Seems like a reasonable

    thing
    > to
    > > want to do. However, SetStream() takes an ofstream parameter by value

    and
    > > then assigns it to the member ofstream object. There are two problems
    > > here - ofstream has neither a copy constructor nor an assignment

    operator,
    > > so passing it as a parameter and assigning it are both illegal! This

    > should
    > > have never compiled, but we had a poor compiler (VC++ 6.0) and it was

    let
    > > through. Now that we've upgraded to a more compliant compiler, the

    error
    > is
    > > finally getting caught.
    > >
    > > So, I need to figure out a way to update this stream data member
    > > dynamically. I have considered changing the data member from ofstream

    to
    > > ofstream*, but there's a problem. The initial stream (upon object
    > > construction) would have to be dynamically allocated,

    >
    > Why?


    What other option do I have for getting an initial per-object stream to set
    the member pointer to point at?

    >
    > std::eek:stream *m_pstr;
    > void SetStream(std::eek:stream &new_stream) {m_pstr = &new_stream;} // pass

    by
    > reference and store the address
    >
    > Of course the life of the stream has to be longer than the life of the
    > object, but that can't be helped. To use it:
    >
    > *m_pstr << "whatever";
    >
    > which means it would
    > > have to be deallocated in the destructor. However, the client code that
    > > uses this class passes non-dynamically allocated ofstream objects when

    it
    > > calls SetStream(). So, we can start passing pointers rather than the
    > > objects themselves, but the pointer can't be deallocated by the
    > > destructor... I guess I could use a flag to mark whether the pointer

    > points
    > > to the orignal dynamically-allocated object or not, but there's got to

    be
    > a
    > > more elegant way...
    > >
    > > My earlier attempt (in my original post) at trying to find a way to

    solve
    > > this with reference members was off in la la land because an initializer
    > > list can't initialize a reference member if the class in question has no
    > > copy constructor. If this makes no sense, don't worry about it; there's

    > no
    > > need to go back and look at the original post. It was headed in the

    wrong
    > > direction...
    > >
    > > Thanks again,
    > > Dave
    > >

    >
    >
    >
    > --
    > Cy
    > http://home.rochester.rr.com/cyhome/
    >
    >
    Dave, Nov 6, 2003
    #9
  10. Dave

    Cy Edmunds Guest

    "Dave" <> wrote in message
    news:...
    >
    > "Cy Edmunds" <> wrote in message
    > news:eyvqb.61692$...
    > > "Dave" <> wrote in message
    > > news:...
    > > > Hello all,
    > > >
    > > > Well, I think I need to elaborate upon my previous post. My

    simplified
    > > > version of things did not provide enough context...
    > > >
    > > > I am maintaining a very poor existing code base (isn't it the bane of

    > all
    > > > our existences???). There is a class which contains as a data member

    an
    > > > ofstream object which is used for logging. This object is bound to a

    > log
    > > > file upon object construction, so the stream's ready to write to by

    the
    > > time
    > > > we start doing any real work. So far so good... Where it gets messy

    is
    > > > that there is also a member function SetStream() to change the stream
    > > > dynamically. So, we may log to the initial stream for awhile, and

    then
    > > > decide to start logging to another stream. Seems like a reasonable

    > thing
    > > to
    > > > want to do. However, SetStream() takes an ofstream parameter by value

    > and
    > > > then assigns it to the member ofstream object. There are two problems
    > > > here - ofstream has neither a copy constructor nor an assignment

    > operator,
    > > > so passing it as a parameter and assigning it are both illegal! This

    > > should
    > > > have never compiled, but we had a poor compiler (VC++ 6.0) and it was

    > let
    > > > through. Now that we've upgraded to a more compliant compiler, the

    > error
    > > is
    > > > finally getting caught.
    > > >
    > > > So, I need to figure out a way to update this stream data member
    > > > dynamically. I have considered changing the data member from ofstream

    > to
    > > > ofstream*, but there's a problem. The initial stream (upon object
    > > > construction) would have to be dynamically allocated,

    > >
    > > Why?

    >
    > What other option do I have for getting an initial per-object stream to

    set
    > the member pointer to point at?
    >



    I showed you but you snipped that part out! LOL

    Pass a reference in the argument list and then take its address. I've done
    this before and it works fine.

    Maybe my previous thing was a little cryptic. Here is a more explicit
    example:

    class Funky
    {
    private:
    std::eek:stream *m_pstr;

    public:
    Funky(std::eek:stream &ostr) : m_pstr(&ostr) {} // note & operator

    void SetStream(std::eek:stream &ostr) {m_pstr = &ostr;} // & operator again
    };

    --
    Cy
    http://home.rochester.rr.com/cyhome/
    Cy Edmunds, Nov 6, 2003
    #10
  11. Dave

    Calum Guest

    Dave wrote:
    > What other option do I have for getting an initial per-object stream to set
    > the member pointer to point at?


    You could have a static object. e.g.

    class foo_t
    {
    static bar_t default_bar;
    bar_t *my_bar;
    public:
    foo_t() : my_bar(&default_bar) { }
    void set_bar(my_bar*b) { my_bar = b; }
    bar_t *get_bar() const { return my_bar; }
    };

    ....
    bar_t foo_t::my_bar;

    Doesn't even need to be static for that matter.
    Calum, Nov 7, 2003
    #11
  12. Dave

    Calum Guest

    Calum wrote:
    > Dave wrote:
    >
    >> What other option do I have for getting an initial per-object stream
    >> to set
    >> the member pointer to point at?


    > bar_t foo_t::my_bar;


    I meant

    bar_t foo_t::default_bar;

    I clearly have not tested this code but you get the idea?
    Calum, Nov 7, 2003
    #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. Alexander Stippler
    Replies:
    2
    Views:
    624
    Alexander Stippler
    Jul 4, 2003
  2. =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunion?=

    The temporary vs non-const reference love story

    =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunion?=, Nov 4, 2003, in forum: C++
    Replies:
    13
    Views:
    581
    Ron Natalie
    Nov 6, 2003
  3. John Ky
    Replies:
    9
    Views:
    435
    John Ky
    Feb 23, 2004
  4. Andriy Shnyr

    Reference to temporary

    Andriy Shnyr, Feb 25, 2004, in forum: C++
    Replies:
    1
    Views:
    3,751
    Rolf Magnus
    Feb 25, 2004
  5. Replies:
    7
    Views:
    3,209
    James Kanze
    Feb 12, 2008
Loading...

Share This Page