web-dev-qa-db-ja.com

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

先日、テンプレートのメタプログラミングを行っているときに、奇妙なことに遭遇しました。それは基本的にこの主張に帰着します(私が期待する通り)通過しません。

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

最初は、関数参照を定義する構文上の間違いを犯していると思っていましたが、このアサーションは成功し、そうではないことがわかりました。

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

私も実装してみましたremove_reference私自身、cppreferenceからソースをコピーしましたが、それも機能しませんでした。ここで何が起こっているのですか?

Abominable Function Typesの世界へようこそ。

void() &void()への参照ではありませんvoid(&)()(_remove_reference_t_の場合、void()-_remove_reference_t_が返されます。 )does提供するものが実際に関数型への参照である場合、関数への参照で機能します。

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

_struct C {
    void f() &;
};
_

_&C::f_の型はvoid (C::*)() &です。しかし、メンバーへのすべてのポインターは、一部の型Tの_T C::*_として記述できます。この場合、型Tvoid() &になります。

P0172 も参照してください。

42
Barry

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

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(&)()>>);
13
0x5453