Reference to temporary

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

    Reference to temporary

    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;
    }



  • Ron Natalie

    #2
    Re: Reference to temporary


    "Dave" <better_cs_now@ yahoo.com> wrote in message news:vqj391em2v 3s19@news.super news.com...[color=blue]
    > 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?
    >[/color]

    Use a const reference?


    Comment

    • Rob Williscroft

      #3
      Re: Reference to temporary

      Dave wrote in news:vqj391em2v 3s19@news.super news.com:
      [color=blue]
      > 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;
      > };[/color]

      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.
      --

      Comment

      • Andrey Tarasevich

        #4
        Re: Reference to temporary

        Dave wrote:[color=blue]
        > ...
        > 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;
        > }
        > ...[/color]

        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

        Comment

        • Andrey Tarasevich

          #5
          Re: Reference to temporary

          Ron Natalie wrote:[color=blue][color=green]
          >>...
          >> 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?
          >>[/color]
          >
          > Use a const reference?
          > ...[/color]

          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

          Comment

          • Cy Edmunds

            #6
            Re: Reference to temporary

            "Dave" <better_cs_now@ yahoo.com> wrote in message
            news:vqj391em2v 3s19@news.super news.com...[color=blue]
            > 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?[/color]

            [snip]

            Just change the reference to an object:

            class foo_t
            {
            private:
            bar_t;
            };


            Comment

            • Dave

              #7
              Re: Reference to temporary

              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


              Comment

              • Cy Edmunds

                #8
                Re: Reference to temporary

                "Dave" <better_cs_now@ yahoo.com> wrote in message
                news:vqjkt46k6d 7q18@news.super news.com...[color=blue]
                > 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[/color]
                time[color=blue]
                > 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[/color]
                to[color=blue]
                > 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[/color]
                should[color=blue]
                > 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[/color]
                is[color=blue]
                > 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,[/color]

                Why?

                std::ostream *m_pstr;
                void SetStream(std:: ostream &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[color=blue]
                > 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[/color]
                points[color=blue]
                > to the orignal dynamically-allocated object or not, but there's got to be[/color]
                a[color=blue]
                > 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[/color]
                no[color=blue]
                > need to go back and look at the original post. It was headed in the wrong
                > direction...
                >
                > Thanks again,
                > Dave
                >[/color]



                --
                Cy



                Comment

                • Dave

                  #9
                  Re: Reference to temporary


                  "Cy Edmunds" <cedmunds@spaml ess.rochester.r r.com> wrote in message
                  news:eyvqb.6169 2$ZC4.39339@twi ster.nyroc.rr.c om...[color=blue]
                  > "Dave" <better_cs_now@ yahoo.com> wrote in message
                  > news:vqjkt46k6d 7q18@news.super news.com...[color=green]
                  > > 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[/color][/color]
                  all[color=blue][color=green]
                  > > 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[/color][/color]
                  log[color=blue][color=green]
                  > > file upon object construction, so the stream's ready to write to by the[/color]
                  > time[color=green]
                  > > 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[/color][/color]
                  thing[color=blue]
                  > to[color=green]
                  > > want to do. However, SetStream() takes an ofstream parameter by value[/color][/color]
                  and[color=blue][color=green]
                  > > then assigns it to the member ofstream object. There are two problems
                  > > here - ofstream has neither a copy constructor nor an assignment[/color][/color]
                  operator,[color=blue][color=green]
                  > > so passing it as a parameter and assigning it are both illegal! This[/color]
                  > should[color=green]
                  > > have never compiled, but we had a poor compiler (VC++ 6.0) and it was[/color][/color]
                  let[color=blue][color=green]
                  > > through. Now that we've upgraded to a more compliant compiler, the[/color][/color]
                  error[color=blue]
                  > is[color=green]
                  > > 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[/color][/color]
                  to[color=blue][color=green]
                  > > ofstream*, but there's a problem. The initial stream (upon object
                  > > construction) would have to be dynamically allocated,[/color]
                  >
                  > Why?[/color]

                  What other option do I have for getting an initial per-object stream to set
                  the member pointer to point at?
                  [color=blue]
                  >
                  > std::ostream *m_pstr;
                  > void SetStream(std:: ostream &new_stream) {m_pstr = &new_stream; } // pass[/color]
                  by[color=blue]
                  > 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[color=green]
                  > > have to be deallocated in the destructor. However, the client code that
                  > > uses this class passes non-dynamically allocated ofstream objects when[/color][/color]
                  it[color=blue][color=green]
                  > > 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[/color]
                  > points[color=green]
                  > > to the orignal dynamically-allocated object or not, but there's got to[/color][/color]
                  be[color=blue]
                  > a[color=green]
                  > > more elegant way...
                  > >
                  > > My earlier attempt (in my original post) at trying to find a way to[/color][/color]
                  solve[color=blue][color=green]
                  > > 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[/color]
                  > no[color=green]
                  > > need to go back and look at the original post. It was headed in the[/color][/color]
                  wrong[color=blue][color=green]
                  > > direction...
                  > >
                  > > Thanks again,
                  > > Dave
                  > >[/color]
                  >
                  >
                  >
                  > --
                  > Cy
                  > http://home.rochester.rr.com/cyhome/
                  >
                  >[/color]


                  Comment

                  • Cy Edmunds

                    #10
                    Re: Reference to temporary

                    "Dave" <better_cs_now@ yahoo.com> wrote in message
                    news:vql4pqfqqk 7g57@news.super news.com...[color=blue]
                    >
                    > "Cy Edmunds" <cedmunds@spaml ess.rochester.r r.com> wrote in message
                    > news:eyvqb.6169 2$ZC4.39339@twi ster.nyroc.rr.c om...[color=green]
                    > > "Dave" <better_cs_now@ yahoo.com> wrote in message
                    > > news:vqjkt46k6d 7q18@news.super news.com...[color=darkred]
                    > > > Hello all,
                    > > >
                    > > > Well, I think I need to elaborate upon my previous post. My[/color][/color][/color]
                    simplified[color=blue][color=green][color=darkred]
                    > > > version of things did not provide enough context...
                    > > >
                    > > > I am maintaining a very poor existing code base (isn't it the bane of[/color][/color]
                    > all[color=green][color=darkred]
                    > > > our existences???). There is a class which contains as a data member[/color][/color][/color]
                    an[color=blue][color=green][color=darkred]
                    > > > ofstream object which is used for logging. This object is bound to a[/color][/color]
                    > log[color=green][color=darkred]
                    > > > file upon object construction, so the stream's ready to write to by[/color][/color][/color]
                    the[color=blue][color=green]
                    > > time[color=darkred]
                    > > > we start doing any real work. So far so good... Where it gets messy[/color][/color][/color]
                    is[color=blue][color=green][color=darkred]
                    > > > that there is also a member function SetStream() to change the stream
                    > > > dynamically. So, we may log to the initial stream for awhile, and[/color][/color][/color]
                    then[color=blue][color=green][color=darkred]
                    > > > decide to start logging to another stream. Seems like a reasonable[/color][/color]
                    > thing[color=green]
                    > > to[color=darkred]
                    > > > want to do. However, SetStream() takes an ofstream parameter by value[/color][/color]
                    > and[color=green][color=darkred]
                    > > > then assigns it to the member ofstream object. There are two problems
                    > > > here - ofstream has neither a copy constructor nor an assignment[/color][/color]
                    > operator,[color=green][color=darkred]
                    > > > so passing it as a parameter and assigning it are both illegal! This[/color]
                    > > should[color=darkred]
                    > > > have never compiled, but we had a poor compiler (VC++ 6.0) and it was[/color][/color]
                    > let[color=green][color=darkred]
                    > > > through. Now that we've upgraded to a more compliant compiler, the[/color][/color]
                    > error[color=green]
                    > > is[color=darkred]
                    > > > 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[/color][/color]
                    > to[color=green][color=darkred]
                    > > > ofstream*, but there's a problem. The initial stream (upon object
                    > > > construction) would have to be dynamically allocated,[/color]
                    > >
                    > > Why?[/color]
                    >
                    > What other option do I have for getting an initial per-object stream to[/color]
                    set[color=blue]
                    > the member pointer to point at?
                    >[/color]


                    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::ostream *m_pstr;

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

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

                    --
                    Cy



                    Comment

                    • Calum

                      #11
                      Re: Reference to temporary

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

                      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.

                      Comment

                      • Calum

                        #12
                        Re: Reference to temporary

                        Calum wrote:[color=blue]
                        > Dave wrote:
                        >[color=green]
                        >> What other option do I have for getting an initial per-object stream
                        >> to set
                        >> the member pointer to point at?[/color][/color]
                        [color=blue]
                        > bar_t foo_t::my_bar;[/color]

                        I meant

                        bar_t foo_t::default_ bar;

                        I clearly have not tested this code but you get the idea?

                        Comment

                        Working...