C++ 模板 - 完整指南第 2 版在第 436 页有以下脚注(我的粗体):
Except that
decltype(<i>call-expression</i>)
does not require a nonreference, non-void
return type to be complete, unlike call expressions in other contexts. Usingdecltype(std::declval<T>().begin(), 0)
instead does add the requirement that the return type of the call is complete, because the returned value is no longer the result of thedecltype
operand.
脚注指的是 decltype(std::declval<T>().begin())
用于(无效,基于脚注)来测试调用 .begin()
是否有效在 T
上.使用它的代码如下(为清楚起见,周围有一些文本:
the trick is to formulate the expression that checks whether we can call
begin()
inside adecltype
expression for the default value of an additional function template parameter:#include <utility> // for declval #include <type_traits> // for true_type, false_type, and void_t // primary template: template<typename, typename = std::void_t<>> struct HasBeginT : std::false_type {}; // partial specialization (may be SFINAE’d away): template<typename T> struct HasBeginT<T, std::void_t<decltype(std::declval<T>().begin())>> : std::true_type { };
Here, we use
decltype(std::declval<T>().begin())
to test whether, given a value/object of typeT
(usingstd::declval
to avoid any constructor being required), calling a memberbegin()
is valid.
来自 this previous question of mine , 我明白自 operator,
可以重载,, 0
的作用是触发否则不存在的重载决议,这又需要 std::declval<T>().begin()
的类型完成。
但是,书中的文字(请参阅上面以粗体 突出显示的部分)并未提及operator,
。 ,也没有过载决议。这只是糟糕的措辞吗?或者也许只是从不同的角度看同一件事?或者什么?
最佳答案
作者似乎忘记或忽略了 ,
的可能性正在重载。整个技术在这方面是有缺陷的,不仅仅是措辞。
所以如果begin()
有效并返回完整类型,但 ,
重载并且由于某种原因不能被调用,你会得到一个假阴性。
一个更强大的解决方案是 decltype(void(std::declval<T>().begin()))
.
关于C++ 模板 - 完整指南 : Wording of footnote about decltype and return type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69352671/