std::declval<void>() 是一个有效的表达式吗?

Is std::declval<void>() a valid expression?

据我所知,我无法声明对 void 的右值引用。
例如,以下代码格式错误:

 void f(void &&v) { }

[20.2.6/1](函数模板 declval)我们有一个 declval 的声明,即:

template <class T>
add_rvalue_reference_t<T>
declval() noexcept;

因此,declval<void>(让我说)会导致 void && 中,我猜它和之前的一样是错误的例如。

无论如何,以下最小的工作示例编译:

#include<utility>

int main() {
    decltype(std::declval<void>())* ptr = nullptr;
}

请注意以下内容也是正确的:

static_assert(std::is_same<decltype(std::declval<void>()), void>::value, "!");

我原以为它会像前面提到的那样 void&&(或者更好,我原以为它无法编译)。
实际上,它恰好是任何其他非引用类型的右值引用。
例如:

static_assert(std::is_same<decltype(std::declval<int>()), int&&>::value, "!");

declval<void> 是一个有效的表达式吗?以上代码合法吗?
为什么 void 情况下的行为与任何其他类型不同? (否则它不会起作用 可能是一个答案,如果代码是合法的)。

如果合法,标准在哪里允许这样做?我没能找到案例。
当然,标准说:

The template parameter T of declval may be an incomplete type.

无论如何,这里它会导致不可接受的类型 (void&&),并且它会绕过它丢弃右值引用。

如果 T 是可引用类型,

add_rvalue_reference<T> 只会导致 T&&。所以当Tvoid时,结果就是void。这也是为什么您可以 add_rvalue_reference<int&&> 而不会在尝试构造对引用的引用时出错的原因。 (与左值引用相同。)