0

I'm curious about an idiom, or say technique for class to hold a member reference to the instance of itself like in below

class A
{
public:
    A & instance;
public:
    A():instance(*this){}
};

It works fine in VC11 with 0x enabled, though I'm not sure it works same for other compilers, for that this might not have necessarily referred to the according "this-will-being" object at that moment during instantialization. Could someone specify the semantics of initialization list by demonstrating all assignments here? Is it standard or not?

Yang
  • 777
  • 1
  • 10
  • 19
  • 2
    Why would you need that? – n. m. could be an AI Jun 12 '13 at 03:34
  • `A& instance;` is a reference to an instance. – axon Jun 12 '13 at 03:35
  • @axon: It's a reference to an `A`, actually. – Benjamin Lindley Jun 12 '13 at 03:36
  • Intuitively, I'd say this should be fine. If anything is well-defined at the time the constructor is called, it's the address `this` points to. But, like n.m., I am really curious about why this would ever be useful. – jogojapan Jun 12 '13 at 03:36
  • AFAIK there's no restriction to use the `this` pointer in this way. [class.cdtor] specifies a lot of *other* ways to get undefined behaviour when using the `this` pointer or class members during construction/destruction. The example in /3 shows a valid use of the `this` pointer in the mem-initializer-list. – dyp Jun 12 '13 at 03:38
  • That basically just creates an alias for 'this' pointer, effectively having another way to access attributes. I can't see this as being any useful than using the 'this' pointer. – dchhetri Jun 12 '13 at 03:42
  • @Yang `instance` is a bad name for your variable, because it isn't an instance. – axon Jun 12 '13 at 03:42
  • @jogojapan for example, typically a node class of list contains pointer of its own class type to the prior or next one, which is the way I don't appreciate as pointers are strictly speaking type-unsafe to use. Together with STL I'm hoping another node class holding reference. It would even be possible for distinctive roles of node (head, tail or normal) to be created by partial specialization. – Yang Jun 12 '13 at 03:45
  • @axon assignment in initialization list should take place ahead to construction I suppose. So i'm just wondering `this` there. – Yang Jun 12 '13 at 03:50
  • @Yang: "node class of list" Why are you implementing lists yourself? – SigTerm Jun 12 '13 at 03:51
  • Ok, so to initialize a reference to an object `a` of type `A`, you'd do `A& ref = a.instance;`. But instead, you could simply do `A& ref = a;`. I am not sure I understand what you gain by introducing the `instance` member. (Also, references are probably not a good idea for next/prev pointers in a linked list, because you can never modify what the references refer to.) – jogojapan Jun 12 '13 at 03:52
  • Few other things: you will not be able to reassign references. They'll be *probably* stored as pointers, but that's implementation dependent. I don't see any practical use for this trick... – SigTerm Jun 12 '13 at 03:54
  • @SigTerm I'm not implementing a list. I'm exploring possibilities of implementing through the language intrinsics for in-depth understanding. – Yang Jun 12 '13 at 03:55
  • @Yang: As far as I know, if concept or possibility has no practical application, it is very likely that you'll quickly forget about it. If you'll learn concepts while solving problems that are interesting for you, AND if you'll have fun in the process, you'll learn things faster. At least that's the way things worked for me. – SigTerm Jun 12 '13 at 03:59
  • Also I'd like to know what do you call "type safety" here. You can't really assign pointer of one type to another random type (with exception of void* as destination), you have to explicitly tell compiler "yes, I really want to aim rocket launcher at my foot and pull the trigger, I know what I'm doing". – SigTerm Jun 12 '13 at 04:02
  • @jogojapan Is ref a lvalue or rvalue in `A & ref = a;`? – Yang Jun 12 '13 at 04:02
  • It's an lvalue reference, and the expression `ref` is also itself an lvalue. – jogojapan Jun 12 '13 at 04:05
  • @SigTerm Right, but you have to be intentionally aware of type-safty, the solution to which has been long addressed by reference. – Yang Jun 12 '13 at 04:06
  • @Yang I'd say it's only an identifier in that expression. `ref` in that expression is not used in any way but to declare/introduce a name. – dyp Jun 12 '13 at 04:06
  • @Yang: Let me rephrase that. What situation are you trying to avoid by using reference? – SigTerm Jun 12 '13 at 04:07
  • @jogojapan then how could ref as an lvalue never be modified? – Yang Jun 12 '13 at 04:08
  • @DyP Right, as long as I can modify ref later to rename I suppose it would be fine to use in a node class. – Yang Jun 12 '13 at 04:10
  • 1
    The syntax of C++ is defined such that an expression that was declared as a reference acts as an alias of the original expression. So `ref = 3;` will modify `a`. It will not modify what `ref` refers to. – jogojapan Jun 12 '13 at 04:11
  • @Yang: You cannot ever modify a reference and make it point at another object. It keeps pointing at the same object till the end of its lifetime. – SigTerm Jun 12 '13 at 04:12
  • @jogojapan what if I'm trying to modify what ref refers to? A reference to `ref` is available isn't it? – Yang Jun 12 '13 at 04:20
  • Like SigTerm said, you can't. That's what pointers are there for. And as long as you don't use type casts in an irresponsible way, pointers are sufficiently type-safe. What safety issues are you particularly worried about? – jogojapan Jun 12 '13 at 04:21
  • @jogojapan It's sufficiently type-safe, but not essentially. That should be my worry and yours too. – Yang Jun 12 '13 at 04:30
  • @Yang I still don't think I know what you mean with "type-safe". Could you give an example? – dyp Jun 12 '13 at 04:35
  • Conventionally, we make implicit type conversion to explicit for type safety. The type-safety I mean to concern is about its implicity. – Yang Jun 12 '13 at 04:41
  • @Yang a reference is not more typesafe than a pointer. The only differences are: ***1.** refs are automatically dereferenced via `operator.` (syntactic sugar) **2.** refs can't be redirected to point to another object, so essentially they are `T* const`. **3.** have to be initialized (forced by compiler), together with 2. that means they can't be NULL.* That's all. No magic. On any implementation I know, refs are just implemented via pointers internally. – Arne Mertz Jun 12 '13 at 04:48
  • 1
    @Yang [conv.ptr] (in the C++ Standard) lists the allowed/possible implicit pointer conversions, which are: 1) a conversion **from** a null-pointer constant to a pointer (for `nullptr` etc.) 2) a conversion **to** a `void*` (but not **from** a `void*`) 3) a conversion to a base class pointer. Which of those conversions is not "type-safe"? – dyp Jun 12 '13 at 04:50
  • @ArneMertz So that's the restriction C++ standard enforces on the semantics of reference, not exactly what reference should be like in terms of all kinds of programming languages. – Yang Jun 12 '13 at 05:00
  • @DyP that one from void * to others and as legacy in compatibility it's allowed. – Yang Jun 12 '13 at 05:04
  • @Yang [diff.conv] "ISO C will accept this usage of pointer to void being assigned to a pointer to object type. C++ will not." If you tell your compiler to allow unsafe things (or if you don't tell it NOT to allow unsafe things), then unsafe things are allowed. There's no implicit cast from `void*` to another pointer type in C++, it has to be an explicit cast (although a `static_cast` is sufficient). As I said, explicit casts should be like *warning signs*, indicating a possible problem/unsafety. – dyp Jun 12 '13 at 05:13
  • @DyP Sure, therefore a least possibility of occurrence (user scenarios in continuous developing activities) of such explicit cast from void * to others is exactly the purpose I was trying to apply this trick to node class of list. It's more of a preference, a demonstration of breakthrough about how elimination of pointers could be achieved through wrapping a member reference in class for type-safety in case of the exceptional cast. – Yang Jun 12 '13 at 05:47
  • 1
    @Yang I didn't realize this question was about introducing a meta language design discussion. SO questions are about what the language *is* like. For discussions what it *should be* like maybe isocpp.org's forums are a better place ;-) – Arne Mertz Jun 12 '13 at 05:53
  • I feel great walking through this question with you anyway. As to the design of that node class I'll keep trying before my doubt is gone. – Yang Jun 12 '13 at 06:05
  • @Yang: "how elimination of pointers could be achieved through wrapping a member reference" a friendly advice: in my opinion, programmer's goal should be something like "given existing problem, find the fastest, the most human readable solution that would require the minimum amount of work and maintenance time". "Elemination of pointers" ain't it. Basically, "ideally" you should be able to solve any programming problem with one line of code a six years old would be able to comprehend. In practice, of course, that's impossible unless you're a god of programming or something. (continued) – SigTerm Jun 14 '13 at 00:14
  • @Yang: When you start worrying about "elemination of pointers", you're losing your focus and getting distracted by "interesting" language constructs. In my experience, in situation like that people start wasting development time without getting things done. C++ is incredibly complex/flexible, so it is easy to get distracted. You should know all language constructs and know when to use them without focusing too hard on single technique. When you're trying to get rid of one of available feature, there's something wrong. That's just my opinion, anyway. – SigTerm Jun 14 '13 at 00:18
  • @SigTerm "given existing problem, find the fastest, the most human readable solution that would require the minimum amount of work and maintenance time" is, well in my opinion, an excuse for the satisfactied who refuse to learn techniques that has nothing to do with practice, but in-depth understanding towards pros&cons of programming language. – Yang Jun 14 '13 at 14:23
  • @Yang: "in my opinion, an excuse" This goal is impossible to achieve without learning techniques. Spending a lot of time on some fascinating "new" possibility is fine if programming is your hobby, but if it is your job, it'll get you fired. In real world there are time limits, so you'll need to use everything you know, switch techniques often, while keeping track of time, keeping yourself fed and keeping your client happy. This is much more difficult. In C++ it is very easy to fool yourself into thinking that you're doing something important when you waste development time. Don't do that. – SigTerm Jun 14 '13 at 17:57

1 Answers1

0

If you want a shared pointer to yourself, you can use Boost's enable_shared_from_this. I don't know if there's an easy standard way to accomplish the same thing, but it's just a template so you could conceivably do the same thing without Boost.

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • 2
    "I don't know if there's an easy standard way to accomplish the same thing" -- What about [`std::enable_shared_from_this`](http://en.cppreference.com/w/cpp/memory/enable_shared_from_this) ;) – dyp Jun 12 '13 at 03:42
  • @Antimony Actually I'm not expecting any use of pointer for type safty reason. That's the motivation behind. – Yang Jun 12 '13 at 03:52
  • @Yang It's not clear to me what you mean when you say "type safety". Conversions between pointer types are as restricted as conversions between lvalue references IIRC. – dyp Jun 12 '13 at 04:14
  • @DyP You are right. Then why pointers instead the other way in terms of type safety? Well I should say that codes don't read friendly or comfortable with explicit casts everywhere, at least for me ;-p – Yang Jun 12 '13 at 04:27
  • @Yang Because pointers and references are very different and made/used to for different purposes. There are some things you can do with both, and other things you can do only with one of them but not with the other (see e.g. [this SO question](http://stackoverflow.com/questions/57483/what-are-the-differences-between-pointer-variable-and-reference-variable-in-c)) A lot of explicit casts indicate a design flaw btw, casts are explicit when they can go wrong (and implicit if nothing slow/bad/weird/... can happen). – dyp Jun 12 '13 at 04:35
  • @DyP ...then comes the notion of reference and I think it the solution to type-safety for implicit casts, not one that requires casts to be explicit for type-safety. – Yang Jun 12 '13 at 04:47
  • @Yang any implicit cast possible on pointers is possible on references too, except cast to `void*` – Arne Mertz Jun 12 '13 at 04:50
  • @ArneMertz and that exception is the case where I say reference than pointer in terms of type-safety. – Yang Jun 12 '13 at 05:10
  • @Yang and that exception is not an issue because you typically don't use void pointers, so there's little to no opportunity to accidentally pass an `T*` to e.g. a function accepting `void*`. Anyways, the smart pointers mentioned in this answer are even saver than references. You should use them. – Arne Mertz Jun 12 '13 at 05:50
  • @ArneMertz You know I was tortured when concept of pointer first came to me first in school and left a heavy shadow I can't walk out ever since XD. But seriously, I'm just reluctant to pointers, not any kind. – Yang Jun 12 '13 at 05:57
  • @Yang Make the torture your strength. Embrace pointers and know them ;-) Know how not to use them, but also know when not to avoid them. – Arne Mertz Jun 12 '13 at 06:05