Re: C# Properties, inner classes and CRTP
stroumpf2004-gtalk@yahoo.de wrote:
Thank you for reading everything!
No need to thank me. I do find part of the proposal interesting, and
you obviously put a lot of heart into it.
It seems like "code injection" is a good description of what I'm trying
to do. But this doesn't mean that there is no "is-a" relationship. As I
said, the mechanism does almost the same as CRTP, so most arguments
against my proposal would also bury CRTP.
No, that's not a logical deduction. The other possibility is that you
do not put forward a convincing argument that CRTP is bad and that a
replacement is needed. You argue that CRTP is a nasty workaround, that
"the code is not that nice to read" and "we don't like to depend on
CRTP [...] for an everyday problem". These arguments have only
subjective merit.
Of course, we wouldn't want to program virtual functions in C, hence
the virtual function feature in C++. Having the feature in the language
in this case, promotes and simplifies OOP - a programming paradigm.
In the case of your proposed fragmental classes, I personally don't see
the justification in increasing the complexity of the language by
adding what seems a special purpose feature; a feature that the
language --- so awe-inspiring and elegantly --- is already able to
express in terms of CRTP. The readability improvement of fragmental
classes that you claim is not worth the added complexity to the
language in my view.
CRTP is not obvious, but it's an idiom that is easily learned and which
makes you respect the expressivity of the language. I don't find
fragmental classes any more obvious, and I imagine it would just push
the (novice) programmer into the language documentation to explain what
goes on behind the scenes.
However, as I understand it, concepts can't add data elements to a
class - right? So how would you implement a general CRTP example with
concept_map?
I wouldn't need to. I would use CRTP.
I would use concepts in the cases where I needed to retrofit an
existing class with extra interfaces and default behaviour (injected
code). Adding a Property interface to a class in this manner seems like
an elegant solution.
- CalculatorEngine*, CalculatorEngine& and CalculatorEngine will never
be used as types (except as a base class).
That again enforces my view that inheritance is the wrong solution. The
language just becomes more complex when inheritance has more meanings.
[need for enclosing_object]
Now it's a question of finding a good example. At home I frequently
wish to have direct access to the enclosing object - and people in
forums frequently ask for the same.
Yes, after pressing the send button I recalled that I've actually read
one or more articles about the offsetof hack to implement properties. I
was just side-tracked by the fact that your example did not demonstrate
the need.
In fact I find this part of your proposal interesting, and I agree that
a mechanism with language guarantees is necessary. That said, so far I
find your proposed solution for inner classes too complex and
intertwined with the fragmental class proposal.
As I see it, a solution has the following requirements:
- a guaranteed (portable) mechanism to return the pointer to the
enclosing object given the pointer to an embedded object,
- restrictions ensuring the mechanism only is applicable to truly
embedded objects.
I propose a slightly simpler scheme than yours, in which an embedded
object class is tagged by "embedded". This only allows the type to be
used to declare embedded members. Other usages are forbidden. An
embedded class has access rights to the enclosing class. The
"enclosing_object" keyword is replaced by "C::this" where C is the
enclosing class. The latter avoids adding another keyword. It also
nicely extends to allow the shortcut "C::member" for "C::this->member",
and even to transparent lookup in the namespace of the enclosing class
(i.e. simply "member"). For example:
class C {
float angle_; // Angle in degrees.
public:
embedded struct AngleDeg {
void set (float f) {C::angle_ = ...}
float get () const {return angle_;}
} angle_deg;
embedded struct AngleRad {
void set (float f) {...}
float get () const {...}
} angle_rad;
concept_map <float> Property <AngleDeg>;
concept_map <float> Property <AngleRad>;
};
C::AngleDeg d; // Error: Cannot exist outside C.
You could use CRTP instead of concepts to inject the property
interface/code, but using concepts has the added benefit that
properties can be used in constrained (i.e. type-checked) generic code:
template <Property P>
void foo (P& p) {...}
I think it's a hole in the language to hide an obvious information from
the programmer, and instead make him depend on nasty macros or
technically redundant references.
I agree. The ability to access the enclosed object from an embedded
object should be a proper feature of C++.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]