21

I noted that much of boost and libc++/libstdc++ explicitly provide a default value of zero for SFINAE in code like

// 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>
{
};

However it confuses me as to why this would be expected when they explicitly make the call with 0. I remember hearing somewhere it was an optimization (to speed up the compiler when instantiating the template) but I don't fully understand how that would work. I looked at the standard and it has a section that briefly describes what happens with default-arguments in relation to template argument deduction.

14.8.2

At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.

The last bit there sounds concerning to my question

and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.

However that sounds like the opposite of an optimization if it has to do more work. Does anyone have any reasoning why that 0 must be there, it works without it, but every single example of SFINAE in libc++ at least seems to explicitly put 0 there, even though they never call the function with no arguments.

user2864740
  • 60,010
  • 15
  • 145
  • 220
graphitemaster
  • 3,483
  • 4
  • 19
  • 14
  • 3
    I don't know the exact reason, but maybe to raise "ambiguous call error" when one does not to pass in `0` in call expression, instead of false-negative (as the `...` version matches empty arguments while non-defaulted one does not) – Piotr Skotnicki Oct 18 '14 at 19:33
  • 3
    Isn't it related to null pointer analysis? Like maybe the default zero disables static analysis of null pointers, and this in turn avoids lots of false positives when running clang static analyzers. Might also very slightly speedup compilation for the same reason. Just guessing... You should ask on llvm mailing lists (and back here to enlighten us ;)) – Antoine Nov 07 '14 at 09:00
  • There are all sorts of explanations - it's impossible to know, short of reading the design/implementation documentation for that library or (failing that) asking the developer. It could be something as simple as a guideline in a style guide that the developers of this library are following. – Peter Sep 14 '21 at 10:13
  • Just wild guess - but maybe this is compilation time - I know we might think it should be easier to compile without default arg value -- but maybe for this very compiler it is opposite - however I doubt it is a reason. – PiotrNycz Mar 22 '23 at 14:34

0 Answers0