Re: Using this in initialization list??
On May 6, 6:22 am, Neelesh <neelesh.bo...@gmail.com> wrote:
On May 6, 5:36 am, huil...@gmail.com wrote:
Is the following code valid?
template < typename F >
struct base1
{
base1(const F& f):f(f){}
const F& f;
};
template < typename E1, typename E2 >
struct base2
{
base2(const E1& e1, const E2& e2):e1(e1),e2(e2){}
const E1& e1;
const E2& e2;
};
template < typename F1, typename F2 >
struct derived : base1<F1>
,base2<base1<F1>,F2>
{
derived(const F1& f1, const F2& f2)
:base1<F1>(f1)
,base2<base1<F1>,F2>(static_cast<base1<F1> const&>(*thi=
s), f2) // is
this okay?
{}
};
Yes, the code is valid and the static_cast is not needed.
12.6.2p7
...because the meminitializer are evaluated in the scope of the
constructor, the this pointer can be used in the expressionlist of a
meminitializer to refer to the object being initialized.
No, it's not valid. The expression *this is an lvalue
expression with type derived. Type derived has a non-trivial
constructor. According to =A73.8:
[...] The lifetime of an object of type T begins when:
-- storage with the proper alignment and size for type
T is obtained, and
-- if T is a class type with a non-trivial constructor
(12.1), the constructor call has completed.
Furthermore:
Before the lifetime of an object has started but after
the storage which the object will occupy has been
allocated or, after the lifetime of an object has ended
and before the storage which the object occupied is
reused or released, any pointer that refers to the
storage location where the object will be or was located
may be used but only in limited ways. Such a pointer
refers to allocated storage (3.7.3.2), and using the
pointer as if the pointer were of type void*, is
well-defined. Such a pointer may be dereferenced but the
resulting lvalue may only be used in limited ways, as
described below. If the object will be or was of a class
type with a non-trivial destructor, and the pointer is
used as the operand of a delete-expression, the program
has undefined behavior. If the object will be or was of
a non-POD class type, the program has undefined behavior
if:
[...]
-- the pointer is used to access a non-static data
member or call a non-static member function of the
object, or
-- the pointer is implicitly converted (4.10) to a
pointer to a base class type, or
-- the pointer is used as the operand of a static_cast
(5.2.9) (except when the conversion is to void*, or
to void* and subsequently to char*, or unsigned
char*).
There's no exception that I can see for the this pointer.
Practically, I'm not sure what this means. You definitely
can call non-static member functions of already constructed
sub-objects, and you obviously call the constructor of the
sub-objects, so the compiler must be able to convert the
this pointer at this point. On the other hand, I've had
such conversions actually fail (admittedly only when the
base class in question was a virtual base); in my case,
adding a member function in the base class which did nothing
but return this, and calling it, solved the problem.
(Similarly, I've never heard of it failing in the body of
the constructor, although according to the above text, it's
still undefined behavior.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34