I have something similar to this in my code:
#include <iostream>
#include <cstdlib>
struct Base
{
virtual int Virtual() = 0;
};
struct Child
{
struct : public Base
{
virtual int Virtual() { return 1; }
} First;
struct : public Base
{
virtual int Virtual() { return 2; }
} Second;
};
int main()
{
Child child;
printf("ble: %i\n", ((Base*)&child.First)->Virtual());
printf("ble: %i\n", ((Base*)&child.Second)->Virtual());
system("PAUSE");
return 0;
}
I'd expect this to give this output:
ble: 1
ble: 2
and it does so, when compiled under GCC (3.4.5 I believe).
Compiling and running this under Visual Studio 2008 however, gives this:
ble: 2
ble: 2
What is interesting, is that if I give the Base-derived structs names (struct s1 : public Base), it works correctly.
Which behavior, if any, is correct? Is VS just being prissy, or is it adhering to the standard? Am I missing something vital here?
It appears this is a bug in VS 2008, possibly because it overwrites or ignores the vtable for the first unnamed class in favor of the vtable for the second since the internal names are identical. (When you name one explicitly, the internal names for the vtables are no longer identical.)
As far as I can tell from the standard, this should work as you expect and gcc is right.
It is visible how MSVC is getting it wrong from the debugging symbols. It generates temporary names for the anonymous structs, respectively Child::<unnamed-type-First> and Child::<unnamed-type-Second>. There is however only one vtable, it is named Child::<unnamed-tag>::'vftable' and both constructors use it. The different name for the vtable surely is part of the bug.
There are several bugs reported at connection.microsoft.com that are related to anonymous types, none of which ever made it to "must-fix" status. Not the one you found though, afaict. Maybe the workaround is just too simple.
I can confirm this is a known bug in the VC compiler (and it repos in VC10); the two anonymous classes are incorrectly sharing a vtable.
Anonymous structs are not part of the C++ standard.
Edit: Anonymous structs are kind of an ambiguous term. It can mean two things:
class outer
{
public:
struct {
int a;
int b;
} m_a; // 1
struct {
int c;
}; // 2
union {
int d;
int e;
}; // 3
};
1 is what is going on here, a better name than anonymous struct would be "unnamed struct". The struct type itself doesn't have a name, but the object does (m_a).
2 is also known as an anonymous struct, and isn't legal C++. There is no object name, and the idea is you could access the field 'c' directly on objects of type outer. This compiles only because of a compiler extension in Visual Studio (will fail under /Za)
3 Anonymous unions, by contrast, are legal C++.
I confused the two, because here we're calling #1 an "anonymous struct", and wires in my brain crossed with #2.
Related
I accidentally run into the problem having member variables with the same name in classes used in multiple inheritance. My basic idea was that the member variables are simple "merged", i.e. a multiple declaration happens. The compiler did not tell me even a warning, see the MWE below.
I understand that it is a bad idea to have variables with the same name, so I think it is at least ambiguous to refer to them in the way I do; so I expected at least a warning or maybe an error.
1) Why the compiler does not write out at least a warning?
2) How handling of those variables is solved internally? (I guess aliases like HW::I and Other::I are used, but how they relate to SW1::I and SW2::I?)
#include <iostream>
struct Other { int I;};
struct HW { int I;};
struct SW1 : Other, HW { int I;};
struct SW2 : HW, Other { int I;};
struct D : SW1 { };
struct E : SW2 { };
int main()
{
E* e = new E;
D* d = new D;
e->I = 3;
SW1* pc1 = dynamic_cast<SW1*>(d);
pc1->I = 2;
std::cerr << d->I;
std::cerr << e->I;
SW2* pc2 = dynamic_cast<SW2*>(e);
pc2->I = 1;
std::cerr << d->I;
std::cerr << e->I;
}
Why the compiler does not write out at least a warning?
Because you didn't write anything wrong, dangerous or ambiguous. You or I may be confused, but the compiler has a specific set of lookup rules to handle it.
When you write a class member access expression like e->I, the compiler doesn't just look up the name I, it looks up the sub-object that contains the member named this way, along with the member. It also starts with the most derived object type, and looks "up" at base class sub-object until it finds something (this is also how member name hiding in C++ works, in a nutshell).
So for e->I, it looks for I in E. That search finds nothing, so it goes into the base class subject. It find SW2::I, a name that refers to a unique member defined in SW2. So it stops.
If there was no SW2::I, it will continue looking and find both Other::I and HW::I. Now the same name is found in two different base class sub-object, and we get an ambiguity. Not a warning of ambiguity, but flat out making the expression e->I ambiguous, which is an error.
The compiler is correct not to diagnose any problems with your code. The code, as you've constructed it is not ambiguous. Essentially, a name is ambiguous if it is an equally good match for more than one variable (or class member in your case).
When evaluating e->I, the first candidate found is the I that is a member (via inheritance) of class SW2. The members of I that SW2 inherits from its base classes are not as good a match as the member defined directly by Sw2.
Similarly, pc1->I is unambiguously the member of SW1, d->I is the same, and pc2->I is unambiguously the member of the base class SW2.
Ambiguity would occur in evaluating e->I if SW2 did not have its own member named I (i.e. struct SW2: HW, Other {};( . In that case, when evaluating e->I, the name resolution looks in SW2 for a member named I, and doesn't find it. Resolving the name then considers the two base classes, HW and Other, which both have a member named I. They are equally good matches, so the expression e->I is ambiguous - and the compiler will issue a diagnostic i.e. an error (not just a warning). In that case, it is possible for the programmer to explicitly resolve the ambiguity using the scope (::) operator. For example, e->HW::I or e->Other::I which fully qualifies the name.
You are right that such multiple usage of a name within a class hierarchy is a bad idea. Both because it can be difficult to correctly resolve the ambiguity in a way that makes sense to a compiler, and because mere mortals will often have trouble following the logic.
The variables are not merged, you simply get all 3 of them at the same time. You need to cast the pointer to the right type to access the variable you want.
#include <iostream>
struct Other { int I; };
struct HW { int I; };
struct SW1 : public Other, public HW { int I; };
struct D : public SW1 { };
int main() {
D* d = new D;
d->I = 1;
SW1* pc1 = dynamic_cast<SW1*>(d);
pc1->I = 2;
static_cast<Other*>(pc1)->I = 3;
static_cast<HW*>(pc1)->I = 4;
std::cerr << d->I;
std::cerr << static_cast<Other*>(d)->I;
std::cerr << static_cast<HW*>(d)->I;
}
Prints:
234
I.e. the same object d contains 3 different versions of I, depending on how you view it.
I'm working on some code and stumble onto something like this:
class Foo
{
private:
union {
byte bar;
struct {
byte baz1;
byte baz2;
};
};
};
Now, I'm compiling with warning level 4 under VS 2010 (pure unmanaged) and of course VS complains that nameless struct/union is a nonstandard extension (warning C4201) and I want to fix that warning.
Is there ANY reason at all someone would prefer the above to:
class Foo
{
private:
byte bar;
byte baz1;
byte baz2;
};
Or any reason that changing the former to the latter would break?
I am sure you already know this - if a union is used
memory storage is shared between the members of the union.
Your second example will allocate separate storage for all items
but the first example will not (shared between bar and the anonymous
struct).
Nameless structs /unions are not recommended in general
see this URL:
Why does C++ disallow anonymous structs and unions?
I could see changing example 2 to 1 breaking, but not 1 to 2 breaking
unless you are depending on the fact that the storage is shared in
a union (which is VERY bad practice)..
Setting the compiler warning level to 4 will emit this warning.
Yes, there are reasons why someone would prefer a union to a struct. The two data structures are very different. I'll not go in to the reasons for or against a union here, as that's beyond the scope, but here's a link.
If you want to keep the union, you might be able to do this:
class Foo
{
private:
union {
int bar;
struct {
int baz1;
int baz2;
} thing_;
};
};
Note that Foo now has a member named thing_ of type union.
Sure there is a reason. Your solution requires 50% more space in memory as the version with the union. Moreover, with the union, foo.bar = foo.baz1 for all Foo foo;
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why do multiple-inherited functions with same name but different signatures not get treated as overloaded functions?
This fails to compile in the indicated place with g++ 4.6.1:
enum Ea { Ea0 };
enum Eb { Eb0 };
struct Sa { void operator()(Ea) {} };
struct Sb { void operator()(Eb) {} };
struct Sbroken : Sa, Sb {};
struct Sworks {
void operator()(Ea) {}
void operator()(Eb) {}
};
int main() {
Sworks()(Ea0);
Sbroken()(Ea0); // g++ can't disambiguate Ea vs. Eb
}
Clang 2.8 does compile this code, which makes me uncertain if the code is really valid C++ or not. I was about to conclude optimistically that clang was right and g++ was wrong, but then I made a small change which made clang have a similar error:
enum Ea { Ea0 };
enum Eb { Eb0 };
struct Sa { void f(Ea) {} };
struct Sb { void f(Eb) {} };
struct Sbroken : Sa, Sb {};
struct Sworks {
void f(Ea) {}
void f(Eb) {}
};
int main() {
Sworks().f(Ea0);
Sbroken().f(Ea0); // both clang and g++ say this is ambiguous
}
The only change I made there was to use a named function f rather than operator(). I don't see why this should even matter, but it does: this version does not compile with g++ nor with clang.
I think it has something to do with hiding the function(s) in the base classes, and the GCC's error message doesn't seem to help much, even if you use struct instead of enum : In fact, the error message is misleading, because now Ea and Eb are two different classes, with no implicit conversion from Ea to Eb, the ambiguity shouldn't arise, but GCC seems to disagree with me : http://ideone.com/cvzLW (see the modification also).
Anyway, if you bring the functions in the class scope, explicitly by writing using as:
struct Sbroken : Sa, Sb
{
using Sa::operator();
using Sb::operator();
};
then it works : http://ideone.com/LBZgC
Same with other example as well:
struct Sbroken : Sa, Sb
{
using Sa::f;
using Sb::f;
};
Code : http://ideone.com/3hojd
Trying to understand the actual text in the standard (§10.2) isn't easy,
but there is an example which makes it clear: name lookup for a name x
in the derived class fails if the name isn't present in the derived
class, but it is present in more than one base class, and it isn't
hidden. (Hidden isn't relevant here, as it only intervenes when virtual
inheritance is present.) As far as I can tell, this is the case
regardless of the name of the member; I can find no exception if the
member happens to have the special name operator(). Overload
resolution doesn't come into play, because their is failure in the name
lookup, before the overload set is completely built. I'm pretty sure
that both snippets of code are illegal, and that there is a bug in
clang.
You can use using declarations to inject the names into the derived
class, or you can explicitly define forwarding operators in the derived
class. Once the name is found in the derived class, the compiler stops,
and does not look in the base classes.
When I compile and run this with Visual C++ 2010:
#include <iostream>
int main() {
int subtrahend = 5;
struct Subtractor {
int &subtrahend;
int operator()(int minuend) { return minuend - subtrahend; }
} subtractor5 = { subtrahend };
std::cout << subtractor5(47);
}
I get the correct answer, 42.
Nevertheless, the compiler complains that this is impossible:
Temp.cpp(9) : warning C4510: main::Subtractor : default constructor could not be generated
Temp.cpp(6) : see declaration of main::Subtractor
Temp.cpp(9) : warning C4512: main::Subtractor : assignment operator could not be generated
Temp.cpp(6) : see declaration of main::Subtractor
Temp.cpp(9) : warning C4610: struct main::Subtractor can never be instantiated - user defined constructor required
What's going on?
The first two warnings are just letting you know that the implicitly declared member functions cannot be generated due to the presence of a reference data member.
The third warning is a Visual C++ compiler bug.
All three warnings can be ignored with no ill effects, though you can easily make all three go away by making the reference data member a pointer instead (reference data members are almost never worth the trouble).
The first warning is to tell you that a reference value cannot be defaultly constructed(references are guaranteed to point to some value). Switch the subtrahend to a regular integer and the problem will go away.
I am pretty sure the second warning is of similar nature.
(Just saying, it is generally much better to rely on something like boost::function or a similar implementation(std::tr1::function?) instead of writing this code manually)
It's because the variable subtractor5 is an unnamed struct. If you want to make the errors go away, give the structure used for subtractor5 a name.
For example:
struct subtractor {
:
} subtractor5 = { subtrahend };
I unfortunately don't know enough C++ language-ese to know why it works, but I do know why the warning happens.
A user defined constructor is mandatory in following cases:
Initializing constant data members (const int c_member;).
Initializing reference data members (int & r_member;)
Having a data member whose type doesn't have default constructor. Eg:
class NoDefCtor
{
public:
NoDefCtor(int);
};
class ContainThat
{
NoDefCtor no_ctor_member;
};
Inheriting from a base class, where base class doesn't have default constructor. Almost same as above (NoDefCtor).
In the below code, there are two "equivalent" calls to std::for_each using boost:bind expressions. The indicated line compiles, the indicated failing line fails. The best explanation I can find in the standard amounts to "because we said so". I'm looking for "why the standard indicates this behavior". My suppositions are below.
My question is simply: Why does the indicated line compile and the equivalent following line fail to compile (and I don't want because "the standard says so", I already know that - I will not accept any answers that give this as an explanation; I'd like an explanation as to why the standard says so).
Notes: Although I use boost, boost is irrelevant to this question, and the error in various formats has been reproduced using g++ 4.1.* and VC7.1.
#include <boost/bind.hpp>
#include <iostream>
#include <map>
#include <algorithm>
class Base
{
protected:
void foo(int i)
{ std::cout << "Base: " << i << std::endl; }
};
struct Derived : public Base
{
Derived()
{
data[0] = 5;
data[1] = 6;
data[2] = 7;
}
void test()
{
// Compiles
std::for_each(data.begin(), data.end(),
boost::bind(&Derived::foo, this,
boost::bind(&std::map<int, int>::value_type::second, _1)));
// Fails to compile - why?
std::for_each(data.begin(), data.end(),
boost::bind(&Base::foo, this,
boost::bind(&std::map<int, int>::value_type::second, _1)));
}
std::map<int, int> data;
};
int main(int, const char**)
{
Derived().test();
return 0;
}
The indicated line fails with this error:
main.C: In member function 'void Derived::test()':
main.C:9: error: 'void Base::foo(int)' is protected
main.C:31: error: within this context
As noted, the supposedly equivalent statement above compiles cleanly (and if the offending statement is commented out, runs with the expected result of printing “5”, “6”, “7” on separate lines).
While searching for an explanation, I came across 11.5.1 in the standard (specifically, I’m looking at the 2006-11-06 draft):
An additional access check beyond
those described earlier in clause 11
is applied when a non-static data
member or nonstatic member function is
a protected member of its naming class
(11.2)105) As described earlier,
access to a protected member is
granted because the reference occurs
in a friend or member of some class C.
If the access is to form a pointer to
member (5.3.1), the
nested-name-specifier shall name C or
a class derived from C. All other
accesses involve a (possibly implicit)
object expression (5.2.5). In this
case, the class of the object
expression shall be C or a class
derived from C.
After reading this, it became evidently why the second statement failed while the first succeeded, but then the question came up: What is the rationale for this?
My initial thought was that the compiler was expanding the boost::bind templates, discovering that Base::foo was protected and kicking it out because boost::bind<…> was not a friend. But, the more I thought about this explanation, the less it made sense, because if I recall correctly, as soon as you take the pointer to a member (assuming you initially are within access control of the member), all access control information is lost (i.e. I could define a function that returns an arbitrary pointer to a member that alternately returns a public, protected or private member depending on some input and the returner would be none the wiser).
More I thought about it, and the only plausible explanation I could come up with why it should make a difference was in the case of multiple inheritance. Specifically, that depending on the class layout, the member pointer when calculated from Base would be different than that calculated from Derived.
It's all about "context". In the first call the context of the call is Derived which has access to the protected members of Base and hence is allowed to take addresses of them. In the second the context is "outside of" Derived and hence outside of Base so the protected member access is not allowed.
Actually, this seems logical. Inheritance gives you access to Derived::foo and not to Base::foo. Let me illustrate with a code example:
struct Derived : public Base
{
void callPrivateMethod(Base &b)
{
// this should obviously fail
b.foo(5);
// pointer-to-member call should also fail
void (Base::*pBaseFoo) (int) = &Base::foo; // the same error as yours here
(b.*pBaseFoo)(5);
}
};
The reason for this restriction is enforcement of access control across different classes that share a common base.
This is reinforced by notes in Core Language Defects Report defect #385, the relevant part copied here for reference:
[...] the reason we have this rule is that C's use of inherited protected members might be different from their use in a sibling class, say D. Thus members and friends of C can only use B::p in a manner consistent with C's usage, i.e., in C or derived-from-C objects.
As an example of something this rule prevents:
class B {
protected:
void p() { };
};
class C : public B {
public:
typedef void (B::*fn_t)();
fn_t get_p() {
return &B::p; // compilation error here, B::p is protected
}
};
class D : public B { };
int main() {
C c;
C::fn_t pbp = c.get_p();
B * pb = new D();
(pb->*pbp)();
}
The protected status of D::p is something we want the compiler to enforce, but if the above compiled that would not be the case.