为什么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复制源,但这也不起作用。这里发生了什么?

Answers:


42

欢迎来到可恶函数类型的世界。

void() &与参考void()。拼写方式是这样的void(&)()(如果您remove_reference_t,您会得到回报void()-这remove_reference_t 确实适用于对函数的引用,如果您提供的内容实际上是对函数类型的引用)。

什么void() &实际上指的是你剥离后的类的引用合格成员函数的类型。那是:

struct C {
    void f() &;
};

的类型&C::fvoid (C::*)() &。但是所有指向成员的指针都可以像T C::*某种类型一样编写T,在这种情况下这种类型T就是void() &

另请参阅P0172


3
有人应该为可恶的函数类型提出一个规范的问题。
布莱恩

哇,即使我已经学习并使用了将近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(&)()>>);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.