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

时间:2016-09-01 21:17:43

标签: c++ c++11 language-lawyer void decltype

据我所知,我不能声明对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的行为与任何其他类型的行为不同? (因为如果代码是合法的,那么就不会起作用可能是一个答案。

如果合法,标准允许哪些内容?我找不到这个案子了 当然,标准说:

  

declval的模板参数T可能是不完整的类型。

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

1 个答案:

答案 0 :(得分:10)

如果add_rvalue_reference<T>是可引用类型,则

T&&仅会导致T。因此,当Tvoid时,结果只有void。这也是为什么你可以add_rvalue_reference<int&&>并且在尝试构造对引用的引用时不会出错的原因。 (与左值参考相同。)