2

Triggered by this question I was wondering if there is a legal hack to get an alias to a private nested type (note that the question was about something completely different and also this one is not "how can I access something declared as private?"). Inspired by this answer my first step was to write this:

class foo {
    struct bar{};
    public: void foobar(const bar&){}
};

struct hack {
    template <typename T>
    operator T() { return {}; }
};

int main() {
    foo f;
    //f.foobar(foo::bar());// NOPE: bar is private !!
    f.foobar(hack());      // hm, bar is not private?
} 

And I have to admit, I am already lost. Why is it allowed to let a template deduce a private type? Also considering that

struct no_hack {
    operator foo::bar(){ return {}; }
};

is not allowed (foo::bar is private).

Note that I am not asking what is the motivation behind allowing the hack but rather what parts of the standard can explain this difference? Is type deduction not restricted by private?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 2
    For why this is allowed, [cppreference notes](https://en.cppreference.com/w/cpp/language/access#In_detail): "The intent of this rule is that replacing any `private` with `public` never alters the behavior of the program." If switching from `private` to `public` added implicit conversions to be considered, then behavior could be changed; by having implicit conversions ignore access specifiers, this can't happen. – ShadowRanger Jan 31 '19 at 20:58
  • @ShadowRanger have to admit i cannot really follow you (its already late here ;). My conclusion after reading the dupe is that `bar` actually has to be considered as public because it appears in a public argument list. – 463035818_is_not_an_ai Jan 31 '19 at 21:00
  • 2
    One way to look at it is to see what would be lost if this was not allowed. If a class wants to return some kind of proxy-class (like `std::vector`s `operator[]` for example) the proxy-class would have to be public. This is obviously not ideal as it's an implementation detail that the user (usually) don't need to know or care about. – super Jan 31 '19 at 23:05
  • @super hm, implementation detail in the sense of: users dont **need to** care about, but even if the proxy is declared private, users of the class can easily create proxy objects if they want – 463035818_is_not_an_ai Feb 01 '19 at 09:52
  • @user463035818 Important destinction here is that users of the class can **use** the proxy, but they can't create it. Only the internals of the class can, and it can choose when and how it should be done. – super Feb 01 '19 at 10:00
  • @super depends on the details, in the example in this question I could easily create a `bar` and call methods on it (if it had any) – 463035818_is_not_an_ai Feb 01 '19 at 10:02
  • @user463035818 How would you create a `bar` in main in your example? – super Feb 01 '19 at 10:04
  • @super like [this](https://wandbox.org/permlink/TcDfNL0DRSzn481w). Btw dont get me wrong, i am not trying to insist on anything. I know that `private` is largely a convention (a very useful one) and if you want you can break anything. – 463035818_is_not_an_ai Feb 01 '19 at 10:46
  • Again, I think there's an important distinction here between *easily create* and *going out of my way to create*. But you are right, at this point we're just nit-picking. Your example is not something that would just happen by accident. – super Feb 01 '19 at 10:59
  • @super the reason that i am picking that much is that before my state of knowledge was that, dirty hacks aside, `hello()` is not accesible, now I learned it is (even with not so dirty hacks). Maybe this is something obvious to others, but for me it was an eyeopener :) – 463035818_is_not_an_ai Feb 01 '19 at 11:07

0 Answers0