次のコードでは、最後のアサーションを除くすべてがパスします。
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](鉱山を強調)
1 式
static_cast<T>(v)
の結果は、式v
を型T
に変換した結果です。T
が左辺値参照型または関数型への右辺値参照である場合、結果は左辺値;になります。T
がオブジェクトタイプへの右辺値参照の場合、結果はx値です。それ以外の場合、結果はprvalueです。 _static_cast
_演算子は、定数をキャストしてはなりません。
decltype
は、そのオペランドの値カテゴリを尊重し、左辺値式の左辺値参照を生成します。
その理由は、関数名自体が常に左辺値であるためである可能性があります。そのため、関数型の右辺値は「実際に」現れることができません。そのため、そのタイプへのキャストはほとんど意味がありません。