简体   繁体   中英

Instantiating a function parameter that is of private type

Given a class like this:

class MyClass {
   struct PrivateType {};
public:
   static void func(PrivateType) {}
};

I can't do this because PrivateType is private:

MyClass::func(MyClass::PrivateType());

But I can do this:

MyClass::func({});

So I'm instantiating a private type, what looks like, outside of the class scope. Is that an implicit conversion from an initializer list? If so, when a parameter is implicitly converted, does the conversion take place in scope of the class ie as if it was part of the body of the function? Why is that and is that always the case?

{} is a syntax called braced-init-list . It doesn't have a type or value category and doesn't represent any object or value like an expression does. It therefore also doesn't really make sense to consider something like a conversion from a {} to exist.

There are specific rules separate from those for expressions as arguments on how overload resolution considers _braced-init-list_s as arguments.

There are also rules separate from those for initialization from parentheses when initializing from a braced-init-list . However, after overload resolution, the function parameter is always initialized simply as if the argument was the initializer for the parameter in a copy-initialization, meaning that the PrivateType parameter object, which I will name here private_type , will be initialized as if by

PrivateType private_type = {};

in a local variable definition. However, this initialization always happens in the context of the caller. All of this is true for expressions as function arguments as well.

The initialization with the type as defined in your example would resolve to aggregate initialization, because PrivateType is an aggregate class. Since there are no members or base classes to initialize, the initialization then doesn't do anything.

None of this considers whether PrivateType is accessible ( private ) from the context of the caller, because accessibility only applies when deciding whether a member can be named (where eg overload resolution to a member function, constructor or operator overload counts as named ). You are never using the name PrivateType in the caller though. private does not prevent construction of a member class in any context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM