If I could magically make the C++ grammar context-free, I would. However it's too late for that, the grammar is undecidable and having to use a disambiguator is the price to pay in some cases. The question is what kind of disambiguator do we want : one so bad that everyone puts extra work to avoid needing it, or one that's reasonably usable and can be used coherently in non ambiguous code.
The problem you're talking about is one that the compiler basically
tells you how to fix. "It looks like you tried to write a template
specialization, but you need to put 'template' there." You encountered
a problem and understand what you need to do to solve it.
I think there's a misunderstanding about the nature of the problem. The problem is not that people try to write this kind of code and it fails : this happens once. The problem is that people now have to go out of their way to workaround something so basic, which happens everyday. How many times do programmers accidentally step on the "most vexing parse"? Perhaps, once or twice before they know what's going on. The fix is easy : use "{}" or "=" to declare and initialize variables. You can use that and forget about it because the solution is unobtrusive. You can't forget about having to type ".template" everywhere or turns everything into a deducible parameters : it's both ugly and requires cognitive load, that you could have used to do more interesting things than fixing the C++ grammar.
If having to write 9 extra characters
is enough to make you fundamentally rewrite code, I don't see how
having to write 2 characters would make you stop.
Isn't 2 a lot less than 9? I have no trouble seeing how not interspersing my code with a 9 letter word when most of my identifiers are less than that, and replacing that with a 2 characters punctuator would improve readability.
C++ didn't make
`std::get` a free function because making it a template member of
`tuple` would make it too ugly to call. We did it because it creates a
uniform interface for extracting members which other types (like
`pair`) can participate in.
How would this have been impossible with a member function? Have you ever written an invalid call to "get<>()" ? A member function would be welcome here, I don't want the compiler telling me about the 50 overloads in the std namespace.
Even something like member `get` could be solved by having an overload
that takes a `std::integral_constant` parameter and using template
argument deduction to extract the value from it. You'd probably also
need a special literal suffix to make using integer literals easier to
use, so you could just use `x.get(0_ce)`.
Sure, I know all about the possible workarounds. You can always hack your way around language issues. But I don't want a language that makes me work around itself, I want a language that handles common use cases elegantly.