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

sky*_*ack 14 c++ void decltype language-lawyer c++11

据我所知,我不能声明一个右值引用void.
例如,以下代码格式错误:

 void f(void &&v) { }
Run Code Online (Sandbox Code Playgroud)

[20.2.6/1](函数模板declval)我们得到一个声明declval:

template <class T>
add_rvalue_reference_t<T>
declval() noexcept;
Run Code Online (Sandbox Code Playgroud)

因此,declval<void>(让我说)会导致void &&,我猜这是病态的,以及前面的示例所示.

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

#include<utility>

int main() {
    decltype(std::declval<void>())* ptr = nullptr;
}
Run Code Online (Sandbox Code Playgroud)

请注意,以下情况也是如此:

static_assert(std::is_same<decltype(std::declval<void>()), void>::value, "!");
Run Code Online (Sandbox Code Playgroud)

void&&原以为它会如前所述(或者更好,我期待它无法编译).
实际上,它恰好是任何其他非引用类型的右值引用.
举个例子:

static_assert(std::is_same<decltype(std::declval<int>()), int&&>::value, "!");
Run Code Online (Sandbox Code Playgroud)

是否declval<void>有效表达?上面的代码是否合法?
为什么行为void不同于任何其他类型?(如果代码是合法的,那么它就不会起作用,否则可能是一个答案).

如果它是合法的,标准允许哪些?我找不到案子了.
当然,标准说:

declval的模板参数T可以是不完整类型.

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

GMa*_*ckG 10

add_rvalue_reference<T>仅导致T&&if T是可引用类型.所以,当Tvoid时,结果就是void.这也是为什么你可以add_rvalue_reference<int&&>尝试构造对引用的引用而不会出错的原因.(与左值参考相同.)

  • @skypjack:实际上,我不知道这是怎么回事,你的问题促使我看.:) 好问题. (2认同)