Yes, this is the correct behavior.
Case 1 - type inference
func<int>(d);
The template output type is used to determine the bleh type .
To create an instance of a function template, each template argument must be known, but not every template parameter must be specified. Whenever possible, the compiler will infer missing template arguments from function arguments . This happens when you try to call a function and when you select the address of the function template.
The compiler sees type d as double and therefore infers the actual type for bleh should also be double .
From cppreference , also discussed in ยง 14.8.2 of the C ++ specification;
The output of the template argument is trying to determine the arguments of the template ..., which can be replaced with each parameter P to get the type output by A that matches the type of argument A , ....
If there are several parameters, each P / A pair is output separately, and then the calculated template arguments are combined. If deduction fails or is ambiguous for any P / A pair, or if different pairs give different derived template arguments, or if any template argument is not output or explicitly defined, compilation is not performed.
Case 2
func<int,double>(d);
The type for bleh explicitly set to double , so the compiler will make it like that. The d argument is provided, and since it is also a double , the compiler happily continues. If an argument (i.e., Instead of d ) was provided with a type that was not double , or could not be implicitly converted to double (for example, through promotions, implicit constructors or conversions provided by the user), this will lead to an error.