为什么 `decltype(static_cast<T>(...))` 不总是 `T`?
Why is `decltype(static_cast<T>(...))` not always `T`?
对于以下代码,除了最后一个断言之外的所有断言都通过了:
template<typename T>
constexpr void assert_static_cast_identity() {
using T_cast = decltype(static_cast<T>(std::declval<T>()));
static_assert(std::is_same_v<T_cast, T>);
}
int main() {
assert_static_cast_identity<int>();
assert_static_cast_identity<int&>();
assert_static_cast_identity<int&&>();
// assert_static_cast_identity<int(int)>(); // illegal cast
assert_static_cast_identity<int (&)(int)>();
assert_static_cast_identity<int (&&)(int)>(); // static assert fails
}
为什么最后一个断言失败了,而且 static_cast<T>
并不总是返回 T
?
这在 static_cast
的定义中是硬编码的:
[expr.static.cast] (emphasis mine)
1 The result of the expression static_cast<T>(v)
is the result
of converting the expression v
to type T
. If T
is an lvalue
reference type or an rvalue reference to function type, the result is
an lvalue; if T
is an rvalue reference to object type, the result is
an xvalue; otherwise, the result is a prvalue. The static_cast
operator shall not cast away constness.
decltype
尊重其操作数的值类别,并为左值表达式生成左值引用。
原因可能是函数名本身总是左值,因此函数类型的右值不能出现"in the wild"。因此,转换为该类型可能没有什么意义。
对于以下代码,除了最后一个断言之外的所有断言都通过了:
template<typename T>
constexpr void assert_static_cast_identity() {
using T_cast = decltype(static_cast<T>(std::declval<T>()));
static_assert(std::is_same_v<T_cast, T>);
}
int main() {
assert_static_cast_identity<int>();
assert_static_cast_identity<int&>();
assert_static_cast_identity<int&&>();
// assert_static_cast_identity<int(int)>(); // illegal cast
assert_static_cast_identity<int (&)(int)>();
assert_static_cast_identity<int (&&)(int)>(); // static assert fails
}
为什么最后一个断言失败了,而且 static_cast<T>
并不总是返回 T
?
这在 static_cast
的定义中是硬编码的:
[expr.static.cast] (emphasis mine)
1 The result of the expression
static_cast<T>(v)
is the result of converting the expressionv
to typeT
. IfT
is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; ifT
is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue. Thestatic_cast
operator shall not cast away constness.
decltype
尊重其操作数的值类别,并为左值表达式生成左值引用。
原因可能是函数名本身总是左值,因此函数类型的右值不能出现"in the wild"。因此,转换为该类型可能没有什么意义。