对带花括号的引用类型变量的 decltype
decltype on the variable of reference type with curly braces
考虑以下 code:
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
v1
的类型推断为 int
。同时 v2
的类型预计会被推断为 const int&
。我认为 v1
的第一步可以视为添加一个类型别名 using T = decltype(p);
,然后是 auto v4 = T{};
。编译器如何处理这个表达式(decltype(p){}
或 T{}
)?我知道 {}
部分用于实例化,但是 v1
的结果类型怎么不是引用类型?
还有一个问题:有没有一种方法可以使用明确指出的类型 const int&
(而不是 decltype(p)
)来声明与 v1
相同类型的 v3
变量?
任何指向标准的链接将不胜感激。
(致反对者:如果你反对是因为你认为引用 Scott Meyers 不等同于引用标准,哦好吧......)
正如您可以从 Effective Modern C++ 中读到的那样(增加了 errata 的部分,您可以通过搜索 Case 2:
在 link,这只会让下面的阅读更简单,但这对问题来说并不重要):
If ParamType
is a non-reference [...] if expr
's type is a reference, ignore the reference part. If [...] expr
is const
, ingore that too. If it's volatile
, also ignore that.
其中 param
是声明说明符,在您的情况下只是 auto
,即非引用。
换句话说,您是通过普通 auto
(而不是 auto&
)创建 v1
,即通过复制,因此无论您是否使用实体是不是参考,甚至是 const
或不是(或者 volatile
与否,fwiw),因为你正在复制它。
想想更简单的情况,
int i = 3;
int& p = i;
auto v1 = p;
就v1
而言,它是用一个(i
)还是另一个(p
)名称初始化真的不重要,相同 实体是已知的,因为它将获得该实体具有的任何值的副本。
auto
类型推导就像模板类型推导一样工作(除了它们处理花括号初始化器的方式不同,这在这种情况下不相关),对于它们两者你可以参考 Scott Meyers 的 Effective Modern C++.
auto v4 = T{}
;. How this expression (decltype(p){}
or T{}
) is treated by compiler? I know that {}
part is for instantiation, but how the result type is not a reference type?
结果decltype(p){}
是一个引用类型。 auto
的用法删除了 const
和引用限定符。类型推导解释here,与模板类型推导相同。您可以使用 decltype(auto)
来保留这些限定符(或者,在这种特殊情况下,您可以使用 const auto&
)。
考虑以下 code:
#include <type_traits>
int main() {
const int& p = 42;
auto v1 = decltype(p){};
static_assert(std::is_same_v<decltype(v1), int>);
decltype(p) v2{};
static_assert(std::is_same_v<decltype(v2), const int&>);
// auto v3 = X(const int&)X {};
}
v1
的类型推断为 int
。同时 v2
的类型预计会被推断为 const int&
。我认为 v1
的第一步可以视为添加一个类型别名 using T = decltype(p);
,然后是 auto v4 = T{};
。编译器如何处理这个表达式(decltype(p){}
或 T{}
)?我知道 {}
部分用于实例化,但是 v1
的结果类型怎么不是引用类型?
还有一个问题:有没有一种方法可以使用明确指出的类型 const int&
(而不是 decltype(p)
)来声明与 v1
相同类型的 v3
变量?
任何指向标准的链接将不胜感激。
(致反对者:如果你反对是因为你认为引用 Scott Meyers 不等同于引用标准,哦好吧......)
正如您可以从 Effective Modern C++ 中读到的那样(增加了 errata 的部分,您可以通过搜索 Case 2:
在 link,这只会让下面的阅读更简单,但这对问题来说并不重要):
If
ParamType
is a non-reference [...] ifexpr
's type is a reference, ignore the reference part. If [...]expr
isconst
, ingore that too. If it'svolatile
, also ignore that.
其中 param
是声明说明符,在您的情况下只是 auto
,即非引用。
换句话说,您是通过普通 auto
(而不是 auto&
)创建 v1
,即通过复制,因此无论您是否使用实体是不是参考,甚至是 const
或不是(或者 volatile
与否,fwiw),因为你正在复制它。
想想更简单的情况,
int i = 3;
int& p = i;
auto v1 = p;
就v1
而言,它是用一个(i
)还是另一个(p
)名称初始化真的不重要,相同 实体是已知的,因为它将获得该实体具有的任何值的副本。
auto
类型推导就像模板类型推导一样工作(除了它们处理花括号初始化器的方式不同,这在这种情况下不相关),对于它们两者你可以参考 Scott Meyers 的 Effective Modern C++.
auto v4 = T{}
;. How this expression (decltype(p){}
orT{}
) is treated by compiler? I know that{}
part is for instantiation, but how the result type is not a reference type?
结果decltype(p){}
是一个引用类型。 auto
的用法删除了 const
和引用限定符。类型推导解释here,与模板类型推导相同。您可以使用 decltype(auto)
来保留这些限定符(或者,在这种特殊情况下,您可以使用 const auto&
)。