In this code:
struct
{
auto operator[](const char*)
{
return *this;
}
} m_some_class;
What is type of auto in here?
In this code:
struct
{
auto operator[](const char*)
{
return *this;
}
} m_some_class;
What is type of auto in here?
What is type of
autoin here ?
The type is decltype(m_some_class) - I.e., the return value is of the same type as the variable m_some_class.
Note that the function will return a copy of *this.
If a reference to *this is wanted instead, you can use
auto& or, since C++14, the more generic decltype(auto).
For anonymous structure types, internally the compiler creates a name and the auto in your case return the structure.
You can see below, that your anonymous structure is given name __anon_1_1 and the operator[] function returns object of __anon_1_1 structure. m_some_class is instance of type __anon_1_1
cppinsights website provides a way to understand
your code
struct
{
auto operator[](const char*)
{
return *this;
}
}m_some_class;
compiler version
struct __anon_1_1
{
inline __anon_1_1 operator[](const char *)
{
return __anon_1_1(*this);
}
// inline constexpr __anon_1_1() noexcept = default;
// inline constexpr __anon_1_1(const __anon_1_1 &) noexcept = default;
};
__anon_1_1 m_some_class = __anon_1_1();
The line in the given code:
return *this;
returns the struct m_some_class itself, i.e. the type of the operator[] is:
decltype(m_some_class); // i.e. the type returned is the same as the struct
Also, notice that this will only return a copy instance of the struct since the passed argument isn't given any reference-to operator. Any changes made to the copy of the struct won't affect the original struct.
auto keyword?The auto keyword is typically used in those situations when the type of something is not known to the programmer or it's too lengthy to type either.
Also, the type defined by auto may vary dependent upon the various situations. For instance:
auto len = vector.size(); // len is now defined as size_t in compile time
In some systems, the type of len maybe unsigned long and in my case, it's unsigned long long, here you can't explicitly define which qualifier to use correctly in this indeterminate place. Here we use auto keyword.
All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS.
It is of no significance that the class is anonymous, as the return type is deduced solely from the return statement.
// Denote the type of the anonymous class as 'T'.
// Return type deduced to 'T'
auto operator[](const char*)
{
return *this;
}
// Return type deduced to 'T&'
auto& operator[](const char*)
{
return *this;
}
// Return type deduced to 'T&'
decltype(auto) operator[](const char*)
{
return *this;
}
Details and relevant standard passages follows below.
auto (C++11 and onwards)From [expr.unary.op]/1 [extract, emphasis mine]:
[expr.unary.op]/1 The unary
*operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. [...]
Thus, the result of *this is an lvalue referring to the object onto which the operator call is invoked.
From [dcl.spec.auto]/1 and [dcl.spec.auto]/2 [extract, emphasis mine]:
[dcl.spec.auto]/1 The
autoanddecltype(auto)type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer. [...][dcl.spec.auto]/2 The placeholder type can appear with a function declarator [...] in any context where such a declarator is valid. [...] If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded
returnstatements [...].
From [dcl.type.auto.deduct]/2 and [dcl.type.auto.deduct]/4 [extract, emphasis mine]:
[dcl.type.auto.deduct]/2 A type
Tcontaining a placeholder type, and a corresponding initializere, are determined as follows:
- (2.1) for a non-discarded
returnstatement that occurs in a function declared with a return type that contains a placeholder type,Tis the declared return type andeis the operand of the return statement. If the return statement has no operand, theneisvoid();- [...]
[dcl.spec.auto]/4 If the placeholder is the auto type-specifier, the deduced type
T'replacingTis determined using the rules for template argument deduction. [...][ Example:
const auto &i = expr;The type of
iis the deduced type of the parameteruin the callf(expr)of the following invented function template:template <class U> void f(const U& u);— end example ]
Thus, the return type of the member operator function
auto operator[](const char*)
{
return *this;
}
of the anonymous type, say, T, is the deduced type of the parameter u in the call f(*this) of the following invented function template:
template <class U> void f(U u);
where, as per above, *this is an lvalue, and the return type is thus deduced as T; namely the type of the anonymous class.
Using the same argument, the return of the member operator function
auto& operator[](const char*)
{
return *this;
}
of the anonymous type, say, T, is T&.
As per the argument above it is of no significance that the class is anonymous, as the return type is deduced solely from the return statement.
decltype(auto) (C++14 and onwards)If we were to replace the placeholder return type auto with the placeholder type decltype(auto), different rules governs how the return type is determined.
decltype(auto) operator[](const char*)
{
return *this;
}
From [dcl.type.auto.deduct]/5 [extract, emphasis mine]:
If the placeholder is the
decltype(auto)type-specifier,Tshall be the placeholder alone. The type deduced forTis determined as described in [dcl.type.simple], as thoughehad been the operand of thedecltype.
And, from [dcl.type.simple]/4, [dcl.type.simple]/4.3 applies [extract]:
For an expression
e, the type denoted bydecltype(e)is defined as follows:
- [...]
- (4.4) otherwise, if
eis an lvalue,decltype(e)isT&, whereTis the type ofe;
as, per above, e (the return statement; *this) is a lvalue and neither [dcl.type.simple]/4.1, [dcl.type.simple]/4.2 nor [dcl.type.simple]/4.3 applies here.
Thus, the return type in the OP example modified using the decltype(auto) placeholder type is T&.
It is T, where T is the unnamed type of the class.
Even though it has no known name, the type does still exist, and can be "used" via mechanisms such as auto and decltype.
You probably want auto&, though.