First thing first, this code is completely interpretable on it's own, if you know C++. No documentation on external components is required. It's not depending on anything. You have asked questions which suggest some gaps in basic C++ syntax understanding.
1. Template definition _test
is a template member of class template _has_iterator_category
. It's a template defined within template, so even if you instantiate _has_iterator_category
, you still have to instantiate _test
later, it got a separate template parameter.
2. Technically, it's neither. Because a class template isn't a type and a function template, which _test
is, is not a function.
Constructor's name always matched the most nested enclosing class scope, i.e. _has_iterator_category
in here. _has_iterator_category
doesn't have a constructor declared.
It's a template of function. There are two templates, for different arguments, with different argument type. If both templates can be instantiated through successful substitution of U with concrete type, the function is overloaded.
3. It's not operator * =
, operators cannot have a whitespace in them. It's *
and =
. This is a nameless version of argument list which could be written otherwise:
template <class U> static char _test(typename U::iterator_category *arg = 0);
= 0
is default value of function parameter arg
. As arg
is not being used in this context, its name can be skipped.
The single parameter of function's signature got type U::iterator_category *
. typename
is a keyword required by most but recent C++ standards for a nested type dependant on template parameter. This assumes that U must have a nested type
iterator_category
. Otherwise the substitution of template parameters would fail.
template <class U> static _two _test(...);
Here function signature is "variadic". It means that function may take any number of arguments after substitution of template parameters. Just like printf
.
4. sizeof(_test<T>(0)) == 1
equals to true
if size of _test<T>(0)
result is equal to 1.
The whole construction is a form of rule known as SFINAE - Substitution Failure Is Not An Error. Even if compiler fails to substitute one candidate, it would still try other candidates. The error would diagnosed when all options are exhausted.
In this case the expression sizeof(_test<T>(0))
, which attempts to substitute U
with T
. It's the reason why _test
is made into a nested template. The class is valid, but now we check the function.
If type-id T::iterator_category
is valid, then substitution will be successful, as the resulting declaration will be valid. _test(...)
can be successful too, but then we go to overload choice rules.
A variadic argument always implies type conversion, so there is no ambiguity and _test(...)
will be discarded.
If T::iterator_category
is not a valid type, _two _test(...)
is the only instance of _test()
.
Assuming that sizeof(char)
equals to 1, the constant value
is initialized with true
if return value of expression would be _test<T>(0)
got same size as char
. Which is only true if T::iterator_category
exists.
Essentially this constructs checks, if class T
contains nested type T::iterator_category
in somewhat clumsy and outdated ways. But it is compatible with very early C++ standards as it doesn't use nullptr
or <type_traits>
header.