How can I prevent C++ guessing a second template argument?

What about passing through a using ?

using tfp = void(*)(char const *, char const *);

tfp x = &strf::range;

char const * a = "abcd";

(*x)(a, a+2);

template<typename T>
inline constexpr auto range1_ptr = strf::range<T>;

template<typename T>
inline decltype(auto) range1(T begin, T end) {
    return range1_ptr<T>(begin, end);

Then call range1 instead of strf::range.

range1_ptr<T>(...) can always be used to explicitly call the template taking one template argument, but does not do any deduction from the arguments. range1 replicates the deduction from the original strf::range template.

This works, because [temp.deduct.funcaddr]/1 says that template argument deduction when taking the address of a function without target type of the conversion is done on each candidate function template as if the parameter and argument lists of a hypothetical call were empty. So the second template argument cannot be deduced for the second overload with two template parameters. The only candidate left is the first overload, which will be chosen as the target of the function pointer.

As long as there is no second candidate function template for which a valid template-id with only one argument can be formed, range1_ptr can always be used to call the function template taking one argument unambiguously. Otherwise, the instantiation of range1_ptr will give an error because of ambiguity.