我注意到,很多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放在那里,尽管他们从来没有使用任何参数调用函数。
发布于 2021-02-14 20:21:54
您提供一个默认值,因为您希望能够不提供该参数,尽管条件仍然是检查的!
示例:
template<typename T,
typename std::enable_if<
std::is_floating_point_v<T>
>::type = 0>
void foo() { std::cout << "1"; }然后,只需一个模板参数就可以在主目录中调用此函数!更好的是,人们甚至不需要命名第二个参数,因为它是未使用的。
在函数foo的输入中给出参数时的类似示例
template<class T>
void foo(T t,
typename std::enable_if<
std::is_floating_point_v<T>
>::type = 0) { std::cout << "2"; }然后,您可以给函数foo提供第二个参数,但通常不想这样做。
https://stackoverflow.com/questions/26443573
复制相似问题