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
How to Add Additional Libraries to Visual Studio Project
How to Pass a Member Function Where a Free Function Is Expected
Legality of Cow Std::String Implementation in C++11
C++ Templates That Accept Only Certain Types
How to Detect Reliably MAC Os X, Ios, Linux, Windows in C Preprocessor
Difference Between Static and Shared Libraries
Programmatically Find the Number of Cores on a Machine
When to Use Inline Function and When Not to Use It
Does C++ Support Compile-Time Counters
Floating Point Division VS Floating Point Multiplication
Difference Between an Int and a Long in C++
How to Iterate Over Cin Line by Line in C++
Which, If Any, C++ Compilers Do Tail-Recursion Optimization
How to Implement an Stl-Style Iterator and Avoid Common Pitfalls
How to Implement the Factory Method Pattern in C++ Correctly