From: Razvan Cojocaru on
> template <class StringT>
> struct A
> {
> A (StringT const &str) : str(str) { }
> StringT const &str;
> };
> The problem is that the constructor allows passing temporaries, which
> get destroyed as soon as the constructor finishes executing, not after
> the object is destroyed.
>
> Please let me know if you have any better solutions to my problem.

That seems like a rather convoluted way of trying to achieve this
(template part ommited as it seem irrelevant for the purposes of our
discussion):

struct A
{
A(const std::string& s) : str(s) {}
/* const, if you prefer */ std::string str;
}

Why is it terribly important to have a reference struct member, instead
of a regular string? Even if you're using (non-const) references, you
should be aware that if the string you're referring to in the struct
goes out of scope (destroyed) somewhere, and the struct instance
doesn't, you still have a big problem. So the safest (and simplest) way
is to simply copy the contents of the constructor string to the member
data string (if nothing else, because how else would you cover the case
you've described, where a temporary string gets constructed when passed
to A(), then destroyed?).


Cheers,
--
Razvan Cojocaru
KeyID: 0x04CA34DE


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Razvan Cojocaru on
> Use a const pointer. Use it for the argument passing and if it's not too
> much hassle also use it for the member.
>
> Bottom line for me is: Always use pointers for these parameters.
> Use a pointer member in "90%" of cases.

I don't see the difference between his problem using a non-const
reference and what would ensue if he uses a const pointer (since a
reference is pretty much the functional equivalent of a const pointer,
dereferencing and checking for NULL aside).


--
Razvan Cojocaru
KeyID: 0x04CA34DE


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Martin B. on
Goran wrote:
> On May 30, 1:39 am, M Stefan <mstefa...(a)gmail.com> wrote:
>> Hello. I am trying to write a class similar to this:
>> template <class StringT>
>> struct A
>> {
>> A (StringT const &str) : str(str) { }
>> StringT const &str;};
>>
>> The problem is that the constructor allows passing temporaries, which
>> get destroyed as soon as the constructor finishes executing, not after
>> the object is destroyed.
>> (....)
>> Please let me know if you have any better solutions to my problem.
>
> In languages like C and C++, there are no, zilch, nada solutions. You
> have to handle lifetime of your stuff at any point manually. That's
> how the language works, so use it that way. You passed a temporary and
> stored a reference to it. That does not work, end of.
>
> Goran.
>
> P.S. Martin B's "solution" isn't, e.g.
>
> class x
> { public:
> x(const TYPE* p) : _r(*p) {}
> TYPE& _r;
> };
>
> is broken with
>
> x(NULL); // bad x._r, no help from compiler
>
> and
>
> x(&TYPE()); // bad x._r, no help from compiler
>

I never ever claimed that my proposal is a solution to lifetime
management! What I continue to claim is that /if/ you need to reference
any object like in the OP, then you should use a pointer [1], because
the conversion rules for (const-)references make it nearly impossible to
get it right.

br,
Martin

[1]: Yes, a smart-pointer would be best, but that's not always possible.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Dragan Milenkovic on
Dragan Milenkovic wrote:
> M Stefan wrote:
>> Hello. I am trying to write a class similar to this:
>> template <class StringT>
>> struct A
>> {
>> A (StringT const &str) : str(str) { }
>> StringT const &str;
>> };
>> The problem is that the constructor allows passing temporaries, which
>> get destroyed as soon as the constructor finishes executing, not after
>> the object is destroyed.
>[snip]
> IMHO, it's best to clearly document the purpose and functionality of A.
>
> And now for other solutions. Clearly, the C++ way to do things is
> as in your "solution 3". You worry too much about performance.

I didn't read carefully. You want to change only the constructor,
while I had in mind changing only the member field. So, either
make it StringT or shared_ptr<StringT> or pointer/reference
and write a nice documentation.

Someone else argumented that making it a pointer is not different
than making it a reference. Well, apart from gaining operator=
(should one need it), you might also force a (clueless) user actually
_think_ about what he/she is doing while typing operator "&". :-)

--
Dragan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]