|
|||
|
If a class inheriting is a member of a same name from two distinct
bases, as in the following example: struct A { int a; A() : a(1) { } }; struct B { int a; B() : a(1) { } }; struct C : public A,B { int getA() { return a; } }; int main(int argc,char **argv) { struct C c; return c.getA(); } the compiler clearly refuses the code on the basis that C::a could be either A::a or B::a. Somehow, I had the expectation that inserting a struct C : public A,B { using A::a; // <--- int getA() { return a; } }; should resolve this ambiguity, as it expresses what I would prefer to do, but apparently, this is not the case. In this very harmless example, replacing a by A::a in the getA() method would do, but in my real-life example the number of required changes is a bit too large to make this a convenient approach. The class layout found above (approximately) was the outcome of a necessary refactoring of other code parts and the need of the two (instead of one) base classes having access to the same identical data. My questions: *) What is the rationale of not allowing the "using" directive to resolve the ambiguity? It seems rather straight forward for me, but I believe the compiler is correct here and it is a language design issue. I would prefer to understand why the language does not make use of this simple alternative. *) Which other options do I have in this specific case? Note that in my case I can even ensure that the values of the two "a" are constant and identical throughout the life time of the classes, though I'm also happy to discuss this issue in cases where this does not hold. virtual inheritance where I move A::a into a common virtually derived base class comes to my mind - any other options? Thanks, Thomas -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|
||||
|
||||
|
|
|
|||
|
On 2012-02-22 17:11, Thomas Richter wrote:
> If a class inheriting is a member of a same name from two distinct > bases, as in the following example: > > struct A { > int a; > > A() > : a(1) > { } > }; > > struct B { > int a; > > B() > : a(1) > { } > }; > > struct C : public A,B { > > int getA() > { > return a; > } > }; > > int main(int argc,char **argv) > { > struct C c; > > return c.getA(); > } > > the compiler clearly refuses the code on the basis that C::a could be > either A::a or B::a. Somehow, I had the expectation that inserting a > > struct C : public A,B { > using A::a; // <--- > int getA() > { > return a; > } > }; > > should resolve this ambiguity, as it expresses what I would prefer to > do, but apparently, this is not the case. Adding the using-declaration should resolve the ambiguity. Which compiler did you test? (I'm not aware of any recent compiler that does not handle this situation properly). HTH & Greetings from Bremen, Daniel Krügler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Hi! Am 22.02.12 17:11, schrieb Thomas Richter: > *) Which other options do I have in this specific case? You could insert another class between C and A: struct Intermediate : A { int getA() { return a; } }; struct C : Intermediate, B { }; HTH, Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: keyserver x-hkp://pool.sks-keyservers.net iEYEARECAAYFAk9F5DAACgkQhAOUmAZhnmrh/QCdEHNBA868jG9hEO1GKcdavFYv Ln4An1fGaQJb1NtdEi0IjsPQzUbAxa82 =Kv98 -----END PGP SIGNATURE----- -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Am 22.02.2012 17:11, schrieb Thomas Richter:
> If a class inheriting is a member of a same name from two distinct > bases, as in the following example: > > struct A { > int a; > > A() > : a(1) > { } > }; > > struct B { > int a; > > B() > : a(1) > { } > }; > > struct C : public A,B { > > int getA() > { > return a; > } > }; > > int main(int argc,char **argv) > { > struct C c; > > return c.getA(); > } > > the compiler clearly refuses the code on the basis that C::a could be > either A::a or B::a. Somehow, I had the expectation that inserting a > > struct C : public A,B { > using A::a; // <--- > int getA() > { > return a; > } > }; > > should resolve this ambiguity, as it expresses what I would prefer to > do, but apparently, this is not the case. C++03 says that you first collect any declaration of any member name called 'a' declared in any subobject (*subobject*, not class!). A declaration in an object hides a declaration in all its base class subobjects. It then says that a using-declaration "using X::y;" is considered to be from each baseclass-subobjects of type "X". The two interpretations of this originate from the time you adjust the subobject-affinity of a using-declaration. 1) If you first do hiding and then do the adjustment (from C to C::A) in your case, then you end up with a single declaraton found in subobject C::A (found by your using-declaration which did hide both C::A::a and C::B::a). 2) If you first do the adjustment (from C to C::A), and then do hiding, you end up with three declarations found in two different subobjects (C::A and C::B). This will be an error. Only the first choice of interpretation will make your program be valid. Possibly your compiler takes option "2)" and rejects your code for a lookup ambiguity. In DR #39 (http://www.open-std.org/jtc1/sc22/wg...efects.html#39), the committee applied option "1)" for deeming a different code invalid, but they also say that the outcome of that route is undesired. C++11 makes your code unambiguous unambiguously, however compilers need to implement the C++11 rules first. Last time I checked, Clang and GCC didn't do so yet. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Am 25.02.2012 00:49, schrieb Daniel Krügler:
> On 2012-02-22 17:11, Thomas Richter wrote: >> If a class inheriting is a member of a same name from two distinct > Adding the using-declaration should resolve the ambiguity. Which > compiler did you test? (I'm not aware of any recent compiler that does > not handle this situation properly). That's gcc 4.4.5. Hmm. Thanks for noting, this seems to be a compiler bug then. I'll try a later version. So long, Thomas -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|