【发布时间】:2014-12-14 03:10:30
【问题描述】:
我注意到许多 boost 和 libc++/libstdc++ 在类似代码中为 SFINAE 明确提供了一个默认值为零
// libc++ http://llvm.org/svn/llvm-project/libcxx/trunk/include/memory
namespace __has_pointer_type_imp
{
template <class _Up> static __two __test(...);
template <class _Up> static char __test(typename _Up::pointer* = 0);
}
template <class _Tp>
struct __has_pointer_type
: public integral_constant<bool, sizeof(__has_pointer_type_imp::__test<_Tp>(0)) == 1>
{
};
但是,这让我感到困惑,为什么当他们明确地使用 0 进行调用时会出现这种情况。我记得在某处听到这是一种优化(在实例化模板时加速编译器),但我不完全理解如何那行得通。我查看了标准,其中有一个部分简要描述了与模板参数推导相关的默认参数会发生什么。
14.8.2
在模板实参推导过程中的某些点,有必要采用一个使用模板形参的函数类型,并将这些模板形参替换为相应的模板实参。当任何显式指定的模板参数被替换到函数类型中时,这在模板参数推导的开头完成,并且当从默认参数推导或获得的任何模板参数被替换时,在模板参数推导结束时再次完成。
最后一点听起来与我的问题有关
当替换任何从默认参数推导或获得的模板参数时,在模板参数推导结束时再次。
但是,如果必须做更多工作,这听起来与优化相反。有没有人有任何理由为什么 0 必须在那里,没有它它也可以工作,但是 libc++ 中的每个 SFINAE 示例至少似乎都明确地将 0 放在那里,即使他们从未在没有参数的情况下调用该函数。
【问题讨论】:
-
我不知道确切的原因,但可能会在调用表达式中没有传入
0而不是假阴性时引发“模糊调用错误”(如@987654323 @version 匹配空参数,而非默认的不匹配) -
不是和空指针分析有关吗?就像默认的零可能会禁用空指针的静态分析,这反过来又避免了在运行 clang 静态分析器时出现大量误报。出于同样的原因,也可能会略微加快编译速度。只是猜测......你应该在 llvm 邮件列表上询问(然后回到这里来启发我们;))
-
有各种各样的解释 - 如果没有阅读该库的设计/实现文档或(失败)询问开发人员,这是不可能知道的。它可以是这个库的开发人员遵循的样式指南中的指南一样简单的东西。
标签: c++ templates c++11 sfinae libc++