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


38

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

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

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

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

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

回答:


42

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

void() &はへの参照ではありませんvoid()。それをスペルする方法は次のようになりますvoid(&)()(もしあればこれremove_reference_t、あなたが戻ってになるだろうvoid()-であるが、そのremove_reference_t ない機能への参照での作業を、あなたがそれを提供することは実際には関数型への参照である場合)。

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

struct C {
    void f() &;
};

タイプは&C::fですvoid (C::*)() &。しかし、メンバーへのすべてのポインターは、ある型の場合と同様T C::*に書くことができます。Tこの場合、型Tはそうなりますvoid() &

P0172も参照してください。


3
誰かが忌まわしくない関数型についての標準的な質問を作成する必要があります。
ブライアン、

うわー、C ++を学んで10年近く使用したとしても、C ++に驚かされることはありません。
Kelvin Hu

13

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

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(&)()>>);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.