Saying you should use std::array is well and good, but doesn't help the problem here, because we're dealing with string literals. So understanding the intricacies here can be necessary. Often though, you can just provide an overload or template specialization specifically for strings, and avoid the gotcha that way. A non-template overload will always be preferred to a template function, so that can be a way to make sure all strings are treated the same.
Bonus question: What if you do this?
Do you think the type of z should be "char const *" or "char const[4]"? Try it and see.Code:#include <iostream> #include <typeinfo> template <class T1, class T2> void f(T1 &x, T2 y) { T2 z = "baz"; std::cout << typeid(x).name() << '\n'; std::cout << typeid(y).name() << '\n'; std::cout << typeid(z).name() << '\n'; } int main() { f("foo", "bar"); return 0; }
Why it it that way? Because the writers of the standard though this would be most intuitive and useful. As all this demonstrates, array types are treated specially by template type deduction.