c++ - remove_referenceが関数で機能しないのはなぜですか?




templates types (2)

先日いくつかのテンプレートメタプログラミングを行うときに、奇妙なことに遭遇しました。 基本的には、(私が予想するように)パスするのではなく、この主張に帰着します。

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

最初は、関数参照を定義する構文上の誤りを犯していると思っていましたが、この主張は通り、そうではないことを示しています。

static_assert(std::is_same_v<void()&, void()&>);

また、cppreferenceからソースをコピーして remove_reference 自分で実装しようとしましたが、どちらも機能しませんでした。 ここで何が起こっていますか?


忌まわしい関数型の世界へようこそ。

void() &void() への参照ではあり ません void(&)() なるスペルの方法( remove_reference_t を使用すると void() が返されます。 remove_reference_tremove_reference_t 、実際に関数型への参照である場合、関数への参照に対して機能します。 )。

void() & 実際に参照するのは、クラスを削除した後の参照修飾メンバー関数の型です。 あれは:

struct C {
    void f() &;
};

&C::f のタイプは void (C::*)() & です。 ただし、メンバーへのすべてのポインターは、一部の型 T に対して TC::* として記述できます。この場合、型 Tvoid() & ます。

P0172 も参照してください。


持っている型は、関数への参照ではなく、 参照修飾子を持つ 関数です。

static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);




c++17