我注意到很多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进行调用时,为什么会出现这种情况让我感到困惑。我记得听到某处是优化(在实例化模板时加速编译器)但我不完全了解这将如何工作。我查看了标准,它有一个部分简要描述了与模板参数推导相关的default-arguments会发生什么。
14.8.2
在模板参数推导过程的某些点,有必要采用一个使用模板参数的函数类型,并用相应的模板参数替换这些模板参数。当任何显式指定的模板参数被替换为函数类型时,这在模板参数推断的开始处完成,并且当从默认参数推导或获得的任何模板参数被替换时,再次在模板参数推断的结尾处完成。
最后一点听起来与我的问题有关
并且在模板参数推断结束时再次使用从默认参数推导或获得的任何模板参数进行替换。
然而,如果必须做更多工作,这听起来与优化相反。有没有人有任何理由为什么0必须存在,它没有它,但libc ++中的SFINAE的每个例子至少似乎明确地将0放在那里,即使它们从不调用没有参数的函数。
答案 0 :(得分:1)
我相信Piotr S.对于消除歧义是正确的。例如,请参阅http://www.boost.org/doc/libs/1_47_0/libs/utility/enable_if.html,尤其是第3节。
答案 1 :(得分:0)
你给一个默认值是因为你希望能够不给那个参数,尽管条件仍然是检查!
示例:
template<typename T,
typename std::enable_if<
std::is_floating_point_v<T>
>::type = 0>
void foo() { std::cout << "1"; }
然后就可以只用一个模板参数在 main 中调用这个函数了!更好的是,甚至不需要命名第二个参数,因为它是未使用的。
在函数foo
的输入中给出参数时的类似示例:
template<class T>
void foo(T t,
typename std::enable_if<
std::is_floating_point_v<T>
>::type = 0) { std::cout << "2"; }
然后您可以为函数 foo
提供第二个参数,但您通常不想这样做。