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&&
。所以当T
是void
时,结果就是void
。这也是为什么您可以 add_rvalue_reference<int&&>
而不会在尝试构造对引用的引用时出错的原因。 (与左值引用相同。)
据我所知,我无法声明对 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&&
。所以当T
是void
时,结果就是void
。这也是为什么您可以 add_rvalue_reference<int&&>
而不会在尝试构造对引用的引用时出错的原因。 (与左值引用相同。)