【发布时间】:2016-09-15 17:03:35
【问题描述】:
以下代码在 libstdc++ 上触发静态断言:
#include <utility>
using t = decltype(std::declval<const void>);
应该吗?
这个问题的动机:
以下declval 实现proposed by Eric Niebler(这显然是编译时优化)
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));
如果用户可以合法地观察到std::declval<const void> 的类型,那就值得怀疑了。标准中的签名
template <class T>
add_rvalue_reference_t<T> declval() noexcept;
产生const void () 类型(或C++17 中的const void () noexcept),而提议的版本产生void () 类型(或void () noexcept)。
【问题讨论】:
-
你想用这个来完成什么?
-
@SamVarshavchik,从问题本身来看,问题的原因似乎很清楚......
-
鉴于您是提出这个问题的人,我对自己的回答的信心为零。但是还是扔出去了。 Niebler 提案中的
long重载是否只是为了处理 cv-void? -
@Barry,除非有另一种类型不能很好地应用引用,否则是的。
-
@ClaasBontus,它类似于常见的 SFINAE 技术,在返回类型中使用
decltype来确定表达式是否有效。在这里,不需要检查表达式,只有&&可以应用于类型。请注意,这进一步简化为删除_Up并使用_Tp&&作为返回类型。如果_Tp&&是有效类型,则两个重载都将参与重载决议,并且int胜过long。如果它不是有效类型,则只有第二个重载存在。要了解更多信息,最好的办法是查找表达式 SFINAE 示例。
标签: c++ c++11 language-lawyer