Why How to Use Auto on a Private Type

Why can I use auto on a private type?

The rules for auto are, for the most part, the same as for template type deduction. The example posted works for the same reason you can pass objects of private types to template functions:

template <typename T>
void fun(T t) {}

int main() {
Foo f;
fun(f.Baz()); // ok
}

And why can we pass objects of private types to template functions, you ask? Because only the name of the type is inaccessible. The type itself is still usable, which is why you can return it to client code at all.

Exposing a private type with auto: where can it be useful?

It can be useful if the return type is unspecified. For example, the returned object from a call to std::bind, or formerly boost::bind, is not specified. It is some implementation-defined functor, but you can't actually know its type without looking at implementation details. Before C++11's auto keyword, you could use boost::function as a variable type for storing the result of bind, or you could pass the result of bind to a function which takes a template argument. With C++11, you can store the result object using auto.

So, if a class has some internal type, it is not necessary to expose the actual type to a public API. A user of the class can simply use the auto keyword, and the API documentation can say the type is "unspecified". This keeps the actual internal type a private implementation detail, which can often improve encapsulation.

Accessing private struct of a class using auto

The result of Test::WeirdFunc() is a Priv. This is also the auto-deducted type of val. The auto keyword removes the necessity to name the type of val to be Priv and therefore, the compiler does not complain. As a result, val is of (unmentioned) type Priv and has a public member a, that can be accessed freely.

So the answers to all your questions is: Yes, (as long as you don't "mention" the name of the nested class).

See also: cpp reference on nested classes

Do auto implemented properties use private constructors for their initialization

This piece of code is using object initializer syntax in GetSampleProducts static method.
Object initializers can be used only on types with parameterless constructor, because it's all about syntactic sugar.
This

var p = new Product { Name="West Side Story", Price = 9.99m }

is really translated into this under the hood

var p = new Product();
p.Name = "West Side Story";
p.Price = 9.99m;

It means parameterless constructor is required for var p = new Product(); call. And it will be actually called for each item before the properties are set.

Constructor is private, but as far as GetSampleProducts is inside Product type, it can access Product private members. If you try the same syntax outside of this class it will fail.

So, this

You now have a private parameterless constructor for the sake of the new property-based initialization.

Actually means that constructor isn't used for auto-implemented properties here, it's required for property-based initialization (this term means object initializer), and if you remove it, you will get compilation errors.

What is the benefit of using a private member in a get instead of just having the class auto set the property itself?

public int SomeValue
{
get { return _someValue; }
}
private int _someValue;

is not the equivalent of

public int SomeValue { get; }

If you do the auto property it is equivalent to

public int SomeValue
{
get { return _someValue; }
}
private readonly int _someValue;

You can not change the value of _someValue internally with the auto property but you could with the original code.

That being said, based on your comments, the code was most likely written before C# 6 when auto read only properties where introduced and the original author was too lazy or did not know that he could mark _someValue as readonly and did not intend for _someValue to be changed anyway.

Using a private auto property instead of a simple variable for a programming standard

This does not make too much sense.

I can think of a 'benefit':

  • you can later add logic to the getter and/or setter and be sure it is always passed

but frankly your classes should not become so big that this is useful.

"are there any issues" ?

Your properties won't work as arguments to ref or out parameters.

Instance of private class before auto

It would be quite rare for this to be useful. I would recommend first figuring out why do this rather than how to do it.

There is no way to get A::B to work outside the scope of A given private B. But you can for example provide a public alias in a friend class, and use a similar declaration:

class A{
// ...
friend struct C;
};

struct C {
typedef A::B B;
};

C::B x2 = A::getB();

Instance of private nested class c++

The type B is accessible only to A and friends of A, which means that other code cannot refer to it. On the other hand template type deduction works even for private types, which is needed if you ever wanted to use your private type in any form of template inside A's code.

The auto feature is based on template type deduction and follows the same rules, allowing for the call auto b2 = a.g();.



Related Topics



Leave a reply



Submit