When you are dealing with types that depend on template parameters in a template, the compiler does not know what things are members of this type. Unless you specify otherwise, it is assumed that members are not types, not patterns. Because of this, he tries to process < as less than the operator, but it becomes impossible to parse the expression this way by the time it reaches > .
To get rid of the error, you should use this instead:
call_any<B>::template call<void (&)()>(f);
This explicitly tells the compiler that call is a template, so it should be considered < as the beginning of the template parameters, and not a regular smaller operator.
Template should also be used here:
call_any<B>::call<void()>(f);
The only reason you don't see the error on this line is because there is a way to parse it as not a template:
(call_any<B>::call < void() ) > (f);
Although this is odd, it is syntactically correct, so the compiler passes this line, and the first error you see is the one you mention. However, without the template keyword, you will eventually receive an error message after call_f was actually created (there may be strange ways to work it).
The first two examples are suitable without using the template keyword. Since the type is independent of template parameters, it can be determined that call is a template, while call_f parsed.
You may ask, “Why can't the compiler determine that it is a template? I defined it as a template in the code right above!” The problem is specialization. You can specialize the template and do something completely different than what the primary template indicates:
template<> struct call_any<false> { static const int call = 5; };
This specialization may occur even after defining call_f , so the compiler cannot rely on what the main template for call_any when parsing call_f .