`decltype(static_cast <T>(…))`が常に `T`とは限らないのはなぜですか?


24

次のコードでは、最後のアサーションを除くすべてがパスしています。

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ですか?


T_cast i{1};は得るinvalid initialization of non-const reference of type 'T_cast' {aka 'int (&)(int)'} from an rvalue of type '<brace-enclosed initializer list>'ので、どんな理由であれT_castint (&)(int)ではなくですint (&&)(int)
ケビン

回答:


21

これは、次の定義でハードコード化されていますstatic_cast

[expr.static.cast](私の強調)

1static_­cast<T>(v)の結果は、式vを型に変換した結果ですTが左辺値参照型または関数型への右辺値参照の場合T、結果は左辺値です。Tオブジェクト型への右辺値参照の場合、結果はx値です。それ以外の場合、結果はprvalueです。static_­cast オペレータは、const性を捨ててはなりません。

decltype オペランドの値カテゴリを尊重し、左辺値式の左辺値参照を生成します。

その理由は、関数名自体が常に左辺値であるためである可能性があります。そのため、関数型の右辺値は「実際に」現れることができません。そのため、そのタイプへのキャストはほとんど意味がありません。


この質問は、「関数型のrvalue [s]が[in the] [ing]「in the wild」に
Eric
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.