+8  A: 

No. Objects aren't supposed to need to know where they're being used from in order to work. As far as x is concerned, it's an instance of T. That's it. It doesn't behave differently according to whether it's a member of class C, a member of class D, an automatic, a temporary, etc.

Furthermore, even if the T constructor did know about the instance of C, that instance of C would be incomplete since of course it has not finished construction yet, because its members haven't been constructed. C++ offers you plenty of chances to shoot yourself in the foot, but offering you a reference to an incomplete object in another class's constructor isn't one of them.

The only thing I can think of to approximate your code example is to do something like

#define INIT_FIELDS field1(this), field2(this), field3(this)

immediately after the list of fields, then use INIT_FIELDS in the initializer list and #undef it. It's still duplication, but at least it's all in one place. This will probably surprise your colleagues, however.

The other way to make sure you don't forget a field is to remove the zero-arg constructor from Field. Again, you still have to do the typing, but at least if you forget something the compiler will catch it. The non-DRY nature of initializer lists is, I think, something C++ just has to live with.

Steve Jessop
No-No-No, this #define is <i>ugly</i>
Sergey Skoblikov
Of course, but it's an ugly problem: "how do I not type the stuff I have to type in order for C++ to do what I want?". I didn't say I thought it was a good idea, I said I thought it was the closest I could think of. What I'd do is what I say in the last para.
Steve Jessop
Or, to put it another way, C++ initializer syntax is ugly too, but that doesn't mean nobody uses it ;-)
Steve Jessop
I disagree with your phrase "have to type". Your don't have to. Your have to pay some, but it is possible to implement such a behavior. My code that I quote in question is a part of a working code.
Sergey Skoblikov
Well, one hack I can think of is for the constructor of RecordSet to store "this" in a global, and the constructor of Field to read it and cast it to TestRecordSet*. I call it a hack because I don't like designing for thread-non-safety: is that what the lock's for?
Steve Jessop
Ah, just seen your edit to the question about TLS, so I guess that is what you're doing. Fair enough: it's still not re-entrant but then I doubt you'd ever need it to be. Assuming Field isn't used anywhere else it gets the job done, I suppose.
Steve Jessop
+1  A: 

I don't think so.

Out of pure curiosity, why should it matter ? do you have a context in which this can be useful?

M.

Max
+2  A: 

Adding on to One by One's answer, the actual question you should be asking is: "what is wrong with my solution design that it requires objects to know where they are instanciated?"

Rex M
Nothing wrong, really. Just unusual semantics.
Sergey Skoblikov
A: 

I experiment with things like this in C# all the time - I use reflection to do it.

Consider getting a reflection or code generation library for C++ to help you do what you want to.

Now, I can't tell you how to find a good reflection or code generation library for C++, but that's a different question!

Matt Cruikshank
Reflection is too costly. I better of with what I've got so far.
Sergey Skoblikov
A: 

I am interested in your code. You comment that all fields plus the param attribute have pointers back into the TestRecordSet but that they don't need to be initialized? Or is it the object of the question, how to avoid having to pass the this pointers during construction?

If what you want is avoid adding all fields in the initialization list of your constructor, then it is a flawed objective. You should always initialize all your members in the initialization list and do so in the same order that they are declared in the class (this is not language enforced, but more of a globally learnt experience).

Your use of the try constructor block is just about he only recommended usage for that functionality (Anyone interested read GOTW#66) if it is indeed required. If the RecordSet member has been constructed (and thus the lock acquired) and something goes wrong afterwards in the constructor then [see quote below] the RecordSet will be destroyed and if it uses RAII internally it will free the lock, so I believe that the try/catch may not really be required.

C++03, 15.2 Exception Handling / Constructors and destructors

An object that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution.

David Rodríguez - dribeas
I've edited my question to reflect your post.
Sergey Skoblikov