为什么 const 在像 const T& 这样的表达式中丢失,其中 T 是一个右值引用?
Why is the const lost in an expression like `const T&` where T is an rvalue reference?
我正在处理一个模板化的 class,给定一个传入类型 T
,该模板需要映射到一个“安全的”const 引用。 (这基本上是为了避免在调用时将变异的能力传递给包装函数;请参阅 here 了解真实代码)。
原作者写了类似这样的东西:
template <typename T>
using SafeReference =
std::conditional_t<std::is_scalar_v<T>, T, const T&>;
标量部分在这里并不有趣,但有趣的是 const T&
。这在我看来是正确的,但事实并非如此:
struct Foo{};
using Bar = Foo&&;
// A failing static assert, and a reduced version. It turns out `const Bar&`
// is `Foo&`.
static_assert(std::is_same_v<const Foo&, SafeReference<Bar>>);
static_assert(std::is_same_v<const Foo&, const Bar&>);
我知道 Foo&&
变成 Foo&
由于 reference collapsing 的规则。我也明白 const
可能“丢失”了,因为它试图创建一个引用 const 而不是将引用类型设置为 const。但我什至不知道要 Google 才能确认这一点。
标准的哪一部分说 const
在像 const T&
这样的表达式中“丢失”,用于扩展到右值引用的模板化 T
?
Which part of the standard says that the const is "lost" in an expression like const T& for a templated T expanding to an rvalue reference?
来自dcl.ref/p6:
If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type lvalue reference to cv TR
creates the type lvalue reference to T
, while an attempt to create the type rvalue reference to cv TR creates the type TR
.
引用可能解释了您所看到的行为。
我正在处理一个模板化的 class,给定一个传入类型 T
,该模板需要映射到一个“安全的”const 引用。 (这基本上是为了避免在调用时将变异的能力传递给包装函数;请参阅 here 了解真实代码)。
原作者写了类似这样的东西:
template <typename T>
using SafeReference =
std::conditional_t<std::is_scalar_v<T>, T, const T&>;
标量部分在这里并不有趣,但有趣的是 const T&
。这在我看来是正确的,但事实并非如此:
struct Foo{};
using Bar = Foo&&;
// A failing static assert, and a reduced version. It turns out `const Bar&`
// is `Foo&`.
static_assert(std::is_same_v<const Foo&, SafeReference<Bar>>);
static_assert(std::is_same_v<const Foo&, const Bar&>);
我知道 Foo&&
变成 Foo&
由于 reference collapsing 的规则。我也明白 const
可能“丢失”了,因为它试图创建一个引用 const 而不是将引用类型设置为 const。但我什至不知道要 Google 才能确认这一点。
标准的哪一部分说 const
在像 const T&
这样的表达式中“丢失”,用于扩展到右值引用的模板化 T
?
Which part of the standard says that the const is "lost" in an expression like const T& for a templated T expanding to an rvalue reference?
来自dcl.ref/p6:
If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type lvalue reference to cv
TR
creates the type lvalue reference toT
, while an attempt to create the type rvalue reference to cv TR creates the typeTR
.
引用可能解释了您所看到的行为。