Reference to temporary

D

Dave

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

Ron Natalie

Dave said:
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?
 
R

Rob Williscroft

Dave wrote in
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.
 
A

Andrey Tarasevich

Dave said:
...
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.
 
A

Andrey Tarasevich

Ron said:
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.
 
C

Cy Edmunds

Dave said:
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;
};
 
D

Dave

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
 
C

Cy Edmunds

Dave said:
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
 
C

Cy Edmunds

Dave said:
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
};
 
C

Calum

Dave said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top