18

I am using Visual Studio 2012, and I've found something that is kind of weird. I'm not writing something that I necessarily require to be compatible across multiple compilers, but it may become later(when the code is put on web, users don't want to get compiler errors), but I don't want to write something that is wrong, or just not native.

So this is test code:

class A{
    class B{
        public:
        int i;
    };
    B myB;
public:
    B& getB() { return myB; }
};

int main()
{
    A a;
    A::B& b = a.getB();
    auto& b2 = a.getB();
}

The first line inside main pops error C2248: 'A::B' : cannot access private class declared in class 'A' whereas the second line compiles normally. I wonder, is auto supposed to work like this or is this another bug in Visual Studio?

I don't have any other compiler I can test it on with

You can even write stuff like std::cout << b2.i << "\n"; and it compiles perfectly fine

As per πάντα ῥεῖ's comment, I tried ideone with gcc 4.8.1 and it compiles in the same way, first line is error, second line is perfectly fine.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Creris
  • 1,128
  • 9
  • 20
  • 4
    _`PS: I dont have any other compiler I can test it on with`_: http://isocpp.org/blog/2013/01/online-c-compilers especially http://rise4fun.com/vcpp – πάντα ῥεῖ Jul 06 '14 at 18:13
  • 1
    Interesting. I had never considered the legality of something like this, but it seems to compile with gcc and clang also. – Benjamin Lindley Jul 06 '14 at 18:17
  • With the code in `main` to initialize `b` and `b2`, the output statement leads to [*undefined behavior*](http://en.wikipedia.org/wiki/Undefined_behavior) as `b` and `b2` are references to objects that have been destructed – Some programmer dude Jul 06 '14 at 18:20
  • well, I wrote that in haste, so I just used temporary, but good point, I will edit the question with that one line. Also to add, this doesnt require reference or pointer to compile, you can return instance as well – Creris Jul 06 '14 at 18:22
  • 1
    seems it is actually. But I didnt find it when I searched. Nah lets not lie, I didnt search – Creris Jul 06 '14 at 18:30
  • 1
    @πάνταῥεῖ I believe my list [here of online compilers](http://stackoverflow.com/a/14652386/1708801) is more up to date ... correction or updates are welcome. – Shafik Yaghmour Jul 06 '14 at 18:35
  • @ShafikYaghmour I'd say that your link there exactly points to the same place I've linked in my comment?!? Or did you mean [this one](http://gcc.godbolt.org/) in particular? Looks promising ... – πάντα ῥεῖ Jul 06 '14 at 18:38
  • There's nothing unusual here. The types of lambda expressions and bind expressions are equally "unknowable", but you can still use them in deduced contexts. `auto` is just one more way of performing deduction. – Kerrek SB Jul 06 '14 at 18:57

2 Answers2

10

I believe it's supposed to work like that. Access applies to names, not the entities they refer to.

Even without auto it has always been legal to e.g. pass the result of getB to a function expecting a B.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • 1
    Also, if you create a public `typedef` of a private class, using the `typedef`'d name throws no error while using the private class name does. – Frxstrem Jul 06 '14 at 18:31
  • 3
    Or a typedef :http://stackoverflow.com/questions/13532784/why-can-i-use-auto-on-a-private-type – kobigurk Jul 06 '14 at 18:32
  • re "Access applies to names, not the entities they refer to", *sort of*. For example, C+11 §12.1/1 "Constructors do not have names". Arguably destructors don't have names either, and indeed in C++11 there is at least one (non-normative) note that argues that way. – Cheers and hth. - Alf Jul 08 '14 at 21:20
  • but considering e.g. the duplicate's answers, such fine points may not necessarily matter on SO. – Cheers and hth. - Alf Jul 08 '14 at 21:26
3

auto is supposed to work like that, yes, and yes that means that it can expose private types.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331