在匿名 class 中 returning *this 时,'auto' return 类型是什么类型?
What is the type of an 'auto' return type when returning *this in an anonymous class?
在此代码中:
struct
{
auto operator[](const char*)
{
return *this;
}
} m_some_class;
这里auto
的类型是什么?
给定代码中的行:
return *this;
return结构m_some_class
本身,即operator[]
的类型是:
decltype(m_some_class); // i.e. the type returned is the same as the struct
另外,请注意这只会 return 结构的副本实例,因为传递的参数没有给出任何引用运算符。对结构副本所做的任何更改都不会影响原始结构。
auto
关键字是什么?
auto
关键字通常用于程序员不知道某物的类型或太长而无法输入的情况。
此外,auto
定义的类型可能因不同情况而异。例如:
auto len = vector.size(); // len is now defined as size_t in compile time
在某些系统中,len
的类型可能是 unsigned long
,在我的例子中,它是 unsigned long long
,在这里你不能明确定义在这个不确定的情况下正确使用哪个限定符地方。这里我们使用auto
关键字。
对于匿名结构类型,编译器在内部创建一个名称,在您的情况下自动创建 return 结构。
您可以在下面看到,您的匿名结构被命名为 __anon_1_1
并且 operator[]
函数 return 是 __anon_1_1
结构的对象。 m_some_class
是 __anon_1_1
类型的实例
cppinsights网站提供了一种理解方式
你的代码
struct
{
auto operator[](const char*)
{
return *this;
}
}m_some_class;
编译器版本
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();
What is type of auto
in here ?
类型为 decltype(m_some_class)
- 即,return 值与变量 m_some_class
.
的类型相同
请注意,该函数将 return copy of *this
。
如果需要对 *this
的引用,您可以使用
auto&
或者,从 C++14 开始,更通用的 decltype(auto)
.
以下所有标准参考均指N4659: March 2017 post-Kona working draft/C++17 DIS.
TLDR: 占位符return类型推导
class 是匿名的没有意义,因为 return 类型仅从 return
语句推导出来。
// 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;
}
详细信息和相关标准段落如下。
占位符return类型推导:auto
(C++11及以后)
来自[expr.unary.op]/1[摘录,强调我的]:
[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. [...]
因此,*this
的结果是一个左值,指向调用运算符调用的对象。
来自[dcl.spec.auto]/1 and [dcl.spec.auto]/2[摘录,强调我的]:
[dcl.spec.auto]/1 The auto
and decltype(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 return
statements [...].
来自[dcl.type.auto.deduct]/2 and [dcl.type.auto.deduct]/4[摘录,强调我的]:
[dcl.type.auto.deduct]/2 A type T
containing a placeholder type, and a corresponding initializer e
, are determined as follows:
- (2.1) for a non-discarded
return
statement that occurs in a function declared with a return type that contains a placeholder type,
T
is the declared return type and e
is the operand of the return
statement. If the return statement has no operand, then e
is
void()
;
- [...]
[dcl.spec.auto]/4 If the placeholder is the auto type-specifier, the deduced type T'
replacing T
is determined using the rules
for template argument deduction. [...]
[ Example:
const auto &i = expr;
The type of i
is the deduced type of the parameter u
in the call
f(expr)
of the following invented function template:
template <class U> void f(const U& u);
— end example ]
因此,成员运算符函数的return类型
auto operator[](const char*)
{
return *this;
}
匿名类型的 ,例如 T
,是以下发明函数模板的调用 f(*this)
中参数 u
的推导类型:
template <class U> void f(U u);
其中,按照上述,*this
是一个左值,因此 return 类型被推断为 T
;即匿名的类型 class.
使用相同的参数,return成员运算符函数
auto& operator[](const char*)
{
return *this;
}
的匿名类型,比如说 T
,是 T&
。
根据上面的论点,class 是匿名的没有意义,因为 return 类型仅从 return
语句推导出来。
占位符return类型推导:decltype(auto)
(C++14及以后)
如果我们将占位符 return 类型 auto
替换为占位符类型 decltype(auto)
,则不同的规则决定了如何确定 return 类型。
decltype(auto) operator[](const char*)
{
return *this;
}
来自[dcl.type.auto.deduct]/5[摘录,强调我的]:
If the placeholder is the decltype(auto)
type-specifier, T
shall be the placeholder alone. The type deduced for T
is determined as described in [dcl.type.simple], as though e
had been the operand of the decltype
.
并且,从 [dcl.type.simple]/4, [dcl.type.simple]/4.3 应用 [extract]:
For an expression e
, the type denoted by decltype(e)
is defined as
follows:
- [...]
- (4.4) otherwise, if
e
is an lvalue, decltype(e)
is T&
, where T
is the type of e
;
如上所述,e
(return 语句;*this
)是一个左值,[dcl.type.simple]/4.1, [dcl.type.simple]/4.2 nor [dcl.type.simple]/4.3 均不适用于此处。
因此,使用decltype(auto)
占位符类型修改的OP示例中的return类型为T&
.
它是 T
,其中 T
是 class 的未命名类型。
即使它没有已知的名称,该类型仍然存在,并且可以通过 auto
和 decltype
等机制“使用”。
不过你可能想要 auto&
。
在此代码中:
struct
{
auto operator[](const char*)
{
return *this;
}
} m_some_class;
这里auto
的类型是什么?
给定代码中的行:
return *this;
return结构m_some_class
本身,即operator[]
的类型是:
decltype(m_some_class); // i.e. the type returned is the same as the struct
另外,请注意这只会 return 结构的副本实例,因为传递的参数没有给出任何引用运算符。对结构副本所做的任何更改都不会影响原始结构。
auto
关键字是什么?
auto
关键字通常用于程序员不知道某物的类型或太长而无法输入的情况。
此外,auto
定义的类型可能因不同情况而异。例如:
auto len = vector.size(); // len is now defined as size_t in compile time
在某些系统中,len
的类型可能是 unsigned long
,在我的例子中,它是 unsigned long long
,在这里你不能明确定义在这个不确定的情况下正确使用哪个限定符地方。这里我们使用auto
关键字。
对于匿名结构类型,编译器在内部创建一个名称,在您的情况下自动创建 return 结构。
您可以在下面看到,您的匿名结构被命名为 __anon_1_1
并且 operator[]
函数 return 是 __anon_1_1
结构的对象。 m_some_class
是 __anon_1_1
cppinsights网站提供了一种理解方式
你的代码
struct
{
auto operator[](const char*)
{
return *this;
}
}m_some_class;
编译器版本
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();
What is type of
auto
in here ?
类型为 decltype(m_some_class)
- 即,return 值与变量 m_some_class
.
请注意,该函数将 return copy of *this
。
如果需要对 *this
的引用,您可以使用
auto&
或者,从 C++14 开始,更通用的 decltype(auto)
.
以下所有标准参考均指N4659: March 2017 post-Kona working draft/C++17 DIS.
TLDR: 占位符return类型推导
class 是匿名的没有意义,因为 return 类型仅从 return
语句推导出来。
// 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;
}
详细信息和相关标准段落如下。
占位符return类型推导:auto
(C++11及以后)
来自[expr.unary.op]/1[摘录,强调我的]:
[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. [...]
因此,*this
的结果是一个左值,指向调用运算符调用的对象。
来自[dcl.spec.auto]/1 and [dcl.spec.auto]/2[摘录,强调我的]:
[dcl.spec.auto]/1 The
auto
anddecltype(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
return
statements [...].
来自[dcl.type.auto.deduct]/2 and [dcl.type.auto.deduct]/4[摘录,强调我的]:
[dcl.type.auto.deduct]/2 A type
T
containing a placeholder type, and a corresponding initializere
, are determined as follows:
- (2.1) for a non-discarded
return
statement that occurs in a function declared with a return type that contains a placeholder type,T
is the declared return type ande
is the operand of the return statement. If the return statement has no operand, thene
isvoid()
;- [...]
[dcl.spec.auto]/4 If the placeholder is the auto type-specifier, the deduced type
T'
replacingT
is determined using the rules for template argument deduction. [...][ Example:
const auto &i = expr;
The type of
i
is the deduced type of the parameteru
in the callf(expr)
of the following invented function template:template <class U> void f(const U& u);
— end example ]
因此,成员运算符函数的return类型
auto operator[](const char*)
{
return *this;
}
匿名类型的 ,例如 T
,是以下发明函数模板的调用 f(*this)
中参数 u
的推导类型:
template <class U> void f(U u);
其中,按照上述,*this
是一个左值,因此 return 类型被推断为 T
;即匿名的类型 class.
使用相同的参数,return成员运算符函数
auto& operator[](const char*)
{
return *this;
}
的匿名类型,比如说 T
,是 T&
。
根据上面的论点,class 是匿名的没有意义,因为 return 类型仅从 return
语句推导出来。
占位符return类型推导:decltype(auto)
(C++14及以后)
如果我们将占位符 return 类型 auto
替换为占位符类型 decltype(auto)
,则不同的规则决定了如何确定 return 类型。
decltype(auto) operator[](const char*)
{
return *this;
}
来自[dcl.type.auto.deduct]/5[摘录,强调我的]:
If the placeholder is the
decltype(auto)
type-specifier,T
shall be the placeholder alone. The type deduced forT
is determined as described in [dcl.type.simple], as thoughe
had been the operand of thedecltype
.
并且,从 [dcl.type.simple]/4, [dcl.type.simple]/4.3 应用 [extract]:
For an expression
e
, the type denoted bydecltype(e)
is defined as follows:
- [...]
- (4.4) otherwise, if
e
is an lvalue,decltype(e)
isT&
, whereT
is the type ofe
;
如上所述,e
(return 语句;*this
)是一个左值,[dcl.type.simple]/4.1, [dcl.type.simple]/4.2 nor [dcl.type.simple]/4.3 均不适用于此处。
因此,使用decltype(auto)
占位符类型修改的OP示例中的return类型为T&
.
它是 T
,其中 T
是 class 的未命名类型。
即使它没有已知的名称,该类型仍然存在,并且可以通过 auto
和 decltype
等机制“使用”。
不过你可能想要 auto&
。