为什么remove_reference在函数上不起作用?

时间:2019-11-15 16:01:30

标签: c++ templates types c++17

前几天进行一些模板元编程时遇到了奇怪的事情。基本上可以归结为这个断言没有(正如我期望的那样)通过。

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

起初我以为我在定义函数引用时犯了语法错误,但是这个断言通过了,表明事实并非如此。

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

我也尝试自己实现remove_reference,从cppreference复制源,但这也不起作用。这是怎么回事?

2 个答案:

答案 0 :(得分:41)

欢迎来到令人讨厌的函数类型的世界。

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

答案 1 :(得分:13)

您拥有的类型不是对函数的引用,而是对带有reference qualifier的函数的引用。

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