C++ 使用大括号对引用类型的变量执行decltype

C++ 使用大括号对引用类型的变量执行decltype,c++,language-lawyer,decltype,C++,Language Lawyer,Decltype,考虑以下几点: #包括 int main(){ 常数int&p=42; autov1=decltype(p){}; 静态断言(std::is_same_v); decltype(p)v2{}; 静态断言(std::is_same_v); //自动v3=X(常数int&)X{}; } v1的类型推断为int。同时,v2的类型被预期推断为const int&。我认为v1的第一步可以被视为使用T=decltype(p)再添加一个类型别名案例2:< /代码>在那个链接上,这只会使下面的阅读更简单,但这

考虑以下几点:

#包括
int main(){
常数int&p=42;
autov1=decltype(p){};
静态断言(std::is_same_v);
decltype(p)v2{};
静态断言(std::is_same_v);
//自动v3=X(常数int&)X{};
}
v1
的类型推断为
int
。同时,
v2
的类型被预期推断为
const int&
。我认为
v1
的第一步可以被视为使用T=decltype(p)再添加一个类型别名
autov4=T{}。编译器如何处理这个表达式(
decltype(p){}
T{}
)?我知道
{}
部分是用于实例化的,但是
v1
的结果类型如何不是引用类型呢

还有一个问题:有没有一种方法可以使用显式注释的type
const int&
(而不是
decltype(p)
)来声明与
v1
类型相同的
v3
变量

任何指向标准的链接都将不胜感激。

(对于否决者:如果你因为认为引用Scott Meyers不等于引用标准而否决了投票,哦

你可以从有效的现代C++中读出来(通过搜索那个代码来增加你可以找到的部分>案例2:< /代码>在那个链接上,这只会使下面的阅读更简单,但这不是问题的本质):

如果
ParamType
是非引用[…]如果
expr
的类型是引用,则忽略引用部分。如果[…]
expr
const
,则也应如此。如果它是易变的,也可以忽略它

其中,
param
是声明说明符,在您的情况下,它只是
auto
,即非引用

换句话说,您正在通过普通的
auto
(而不是
auto&
)创建
v1
,即通过复制,因此无论您是否使用引用的实体初始化它,或者甚至使用
const
初始化它(或者
volatile
,fwiw),因为您正在复制它

想想更简单的情况

inti=3;
int&p=i;
自动v1=p;
v1
而言,用一个(
i
)或另一个(
p
)名称初始化它实际上并不重要,因为它将获得该实体具有的任何值的副本

<代码> Audio<代码>类型,演绎工作就像模板类型演绎(除了它们如何处理支持的初始化器,这在这种情况下不相关),对于它们两者,都可以引用Scott Meyers的“有效的现代C++”。

autov4=T{}
;。编译器如何处理这个表达式(
decltype(p){}
T{}
)?我知道
{}
部分是用于实例化的,但是结果类型如何不是引用类型呢


结果
decltype(p){}
是一个引用类型。使用
auto
可以删除
const
和引用限定符。对类型的推断进行了说明,它们与模板类型推断所用的相同。您可以使用
decltype(auto)
来保留那些限定符(或者,在这个特定的例子中,您可以使用
const auto&
)。

起初不相信
decltype(p){}
编译。显然,
{}
值初始化一个临时的
int
,然后将其绑定到引用。呵呵!这回答了你的问题吗?还有一个问题,每个问题1个问题plzDoes
const auto&v3=(const int&){}回答你的
还有一个问题:有没有办法声明v3…?
?@KamilCuk-hmm。。。我已经检查了clang,但它没有编译。在gcc中工作。正如我在回答中所解释的,如果有,它也会删除
volatile
#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 {};
}