问题描述
以下代码在libstdc ++上触发静态断言:
The following code triggers a static assertion on libstdc++:
#include <utility>
using t = decltype(std::declval<const void>);
是否应该?
此问题的动机:
以下 declval
实现(显然是一个编译时优化)
The following declval
implementation proposed by Eric Niebler (which is apparently a compile time optimization)
template<typename _Tp, typename _Up = _Tp&&>
_Up __declval(int);
template<typename _Tp>
_Tp __declval(long);
template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));
declval< const void> 。标准中的签名
would be questionable if a user could legally observe the type of std::declval<const void>
. The signature in the standard
template <class T>
add_rvalue_reference_t<T> declval() noexcept;
会导致类型 const void()
(或C ++ 17中的 const void()noexcept
),而所提出的版本导致 void()
results in the type const void ()
(or const void () noexcept
in C++17), whereas the proposed version results in the type void ()
(or void () noexcept
).
推荐答案
[declval]规定:
[declval] stipulates that:
基本上就是这样。在函数中,odr使用意味着从[basic.def.odr]:
That's basically it. Where functions are concerned, odr-use means, from [basic.def.odr]:
但也:
和[dcl.type.simple]:
And [dcl.type.simple]:
所以在 decltype(std :: declval ,
std :: declval
isn可能被评估,因此它不是odr使用。因为这是 decluration
的一个标准,程序是不合格的,我们不满足它,我认为libstdc ++是错误的发出静态断言。
So in decltype(std::declval<const void>)
, std::declval
isn't potentially evaluated and hence it's not odr-used. Since that's the one criteria on declval
for the program to be ill-formed and we don't meet it, I think libstdc++ is wrong to emit the static assertion.
虽然我不认为这是一个libstc ++的东西。我认为这更多是一个问题,当 static_assert
被触发。 declval
的libstdc ++实现是:
Though I don't think this is a libstc++ thing. I think it's more of a question of when static_assert
s get triggered. The libstdc++ implementation of declval
is:
template<typename _Tp>
struct __declval_protector
{
static const bool __stop = false;
static typename add_rvalue_reference<_Tp>::type __delegate();
};
template<typename _Tp>
inline typename add_rvalue_reference<_Tp>::type
declval() noexcept
{
static_assert(__declval_protector<_Tp>::__stop,
"declval() must not be used!");
return __declval_protector<_Tp>::__delegate();
}
gcc和clang都会触发 static_assert
在这个上下文中(但显然不是 decltype(std :: declval< const void>())
,即使我们在一个未评估的上下文我怀疑这是一个错误,但它可能只是在标准中对触发 static_assert
的正确行为不足。
Both gcc and clang trigger that static_assert
in this context (but obviously not with decltype(std::declval<const void>())
, even though we're in an unevaluated context in both cases. I suspect that's a bug, but it may simply be underspecified in the standard what the correct behavior is with regards to triggering static_assert
s.
这篇关于是否允许在std :: declval上使用decltype< T> (函数本身,而不是调用它的结果)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!