1

Why doesn't this C++11 program work:

template <typename T>
void f(T t = 42) {}

int main() { f(); }

Why can't T be deduced from the default argument 42?

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • If you define a default parameter and obviously know the type, then why even use a template in the first place? – Mario Jun 09 '14 at 12:41
  • This situation requires you to default `T` as well. That might not be the main point of the question, but it does solve the problem. – chris Jun 09 '14 at 12:41
  • @Mario, So that you aren't limited to the type of the default argument. – chris Jun 09 '14 at 12:41
  • Once specialized, of course, but don't think you can do it without, or would definining a default typename be enough? And the default param would be skipped for any other types? Never really tried doing something like this. – Mario Jun 09 '14 at 12:44
  • @Mario, Yes, just give the template parameter a default argument of `int` and anything you pass to `f` will use its value with its type. If you pass nothing, `T` will be `int` and `t` will be 42. – chris Jun 09 '14 at 12:48

1 Answers1

5

14.8.2.5 [temp.deduct.type]:

19 - A template type-parameter cannot be deduced from the type of a function default argument. [...]

The example given is substantially the same as yours.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Any idea why this rule is in place? – Andrew Tomazos Jun 09 '14 at 12:48
  • Might be ambigious? How about `template something(T a, T b = 5, T c = 5.2f);`? – Mario Jun 09 '14 at 12:55
  • Probably due to all the conversions that can take place. Imagine the return type would be also `T`. Then you could have something like `float x = f();`. It would be quite ambiguous for me. Should it be `float x = f()` or `float x = f()`? The latter could introduce quiet bugs due to silent implicit conversions, the 1st one is impossible to guess. – luk32 Jun 09 '14 at 13:01
  • @Mario: No different than `template something(T a, T b, T c); int main() { something(42, 5, 5.2f); }` – Andrew Tomazos Jun 09 '14 at 13:03
  • @luk32: I don't think so. `template T f(T t = 42)` would result in T being deduced to `int` with a call of `f()`, so the function call expression would be of type `int`. – Andrew Tomazos Jun 09 '14 at 13:05
  • Could also be due to the way C/C++ parses files, i.e. top to bottom, left to right. It won't do any crazy backtracking to "correct" types (if you exclude some of C++11's `auto` shenanigans). – Mario Jun 09 '14 at 13:07
  • @AndrewTomazos But the user might not know that, and they would silently get an `int` result, where a `float` would be expected. Precision clipping is enough for me. This is serious, if you imagine more complex types and conversions that can be made. I think this is more of a language design decision. Not one that was made to avoid unnecessary complications in compilers or the language itself. I can be wrong though. – luk32 Jun 09 '14 at 13:09
  • @Mario: Also incorrect, the type is deduced at the function call expression, which is after the default argument has been parsed. – Andrew Tomazos Jun 09 '14 at 13:11
  • 1
    @luk32: Why would the user expect to get an `float`? The return type of a function is not and cannot be deduced in C++ from its surrounding context. Its no different than `int f(); int main() { float x = f(); }`. I seriously doubt this has anything to do with the rationale for the rule. – Andrew Tomazos Jun 09 '14 at 13:16
  • @AndrewTomazos Point taken. :) – Mario Jun 09 '14 at 13:19
  • @AndrewTomazos As I said, I do not think this is a requirement dictated by the reason that it would allow to automatically generate ill-formatted programs, so saying it could be interpreted as something explicit has no value as an argument. I think it's more of a vague language design decision, as taking away one shell from the shotgun you are given to shoot yourself. But the get real reason you'd probably need to ask people involved or knowlegable in the standarization process. Maybe it's a good material for a separate question, if one could make it sound not opinion-based. – luk32 Jun 09 '14 at 13:33
  • @AndrewTomazos, One possibility is that it was written in a time where C++ was much less generous toward type deduction. If the standards committee would reconsider it now and have a chance of accepting it, I think it would be a pretty easy proposal. Strike out this answer's text in the standard and nothing breaks AFAICT because the only way to use it is to remove a default template argument that's already redundant with the default function argument. – chris Jun 09 '14 at 13:46