本文介绍了是否允许在std :: declval上使用decltype< T> (函数本身,而不是调用它的结果)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码在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_asserts 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_asserts.

这篇关于是否允许在std :: declval上使用decltype&lt; T&gt; (函数本身,而不是调用它的结果)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 15:54