查看libstdc ++源代码,发现以下declval
实现:
template<typename _Tp, typename _Up = _Tp&&>
_Up __declval(int); // (1)
template<typename _Tp>
_Tp __declval(long); // (2)
template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));
Eric Niebler的此实现was proposed是编译时优化的方法:他解释说,重载解析比模板实例化要快。
但是,我不明白它是如何工作的。具体来说:
_Up
比仅返回_Tp&&
更好? 与最幼稚的实现相反,这一切如何阻止模板实例化:
template<typename T>
T&& declval() noexcept;
答案 0 :(得分:11)
幼稚的实现并不完全正确。根据标准,declval
定义为([declval]):
template <class T> add_rvalue_reference_t<T> declval() noexcept;
,对于add_rvalue_reference<T>
,标准读取为([meta.trans.ref]):
如果
T
命名可引用类型,则成员typedeftype
命名T&&
;否则,type
命名为T
。
不可引用类型的示例是void
。在这种情况下,由于SFINAE,将使用第二个重载。
关于第一个问题,我看不出任何特殊原因。 _Tp&&
应该可以正常工作。