59
template< class T >
class Foo {
public:
  Foo( T t ) { }
};

int main () {
  int i = 0;
  Foo f( i );
}

In the above code, the compiler complains that template arguments are missing before 'f'. I understand that deducing template arguments for a class from the arguments to the constructor is not part of the standard, but my question is why? Doesn't the compiler have all the information it needs to implicitly instantiate Foo<int> and call its constructor?

Edited to make it clear that I'm calling the constructor with an int (as opposed to a short, long, void*, etc.)

Greg Wilbur
  • 633
  • 5
  • 9
  • 2
    Can't 0 also represent a `bool` or a `char` or a pointer? or is that just an implicit conversion? – mstbaum Apr 16 '15 at 14:38
  • 2
    Regarding the practical problem (not the why), with current C++ just use a factory function. – Cheers and hth. - Alf Apr 16 '15 at 14:38
  • 2
    @mstbaum: While true, I'm not sure that's relevant, since the intent is clearly to follow the same template argument deduction as functions, where that's all clearly specified. – Mooing Duck Apr 16 '15 at 16:37
  • A similar problem exists with `template struct Foo { static void bar(T t); };` - you can't call `Foo::bar(0)` either. Can't deduce the type from the method. – MSalters Apr 16 '15 at 22:04
  • 1
    Your wish became real in C++17 https://en.cppreference.com/w/cpp/language/class_template_argument_deduction – alfC Aug 15 '18 at 08:34

4 Answers4

37

Because nobody has specified how exactly that works. There is a current proposal to the standard committee to make it work. It also lists some of the difficulties:

http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4471.html

Update: Here's the newest version of the proposal:

http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0091r0.html

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • 12
    It might be a good idea to summarise some of the difficulties from the linked article in the answer itself. Although not quite a link-only answer, this would lose a lot of its value if the link died. – IMSoP Apr 16 '15 at 23:03
  • 1
    @IMSoP While you're right about including info, C++'s proposals aren't going anywhere anytime soon – Cole Tobin Apr 17 '15 at 05:32
19

TL;DR: Template specialization


They can, but only template arguments on the function itself, not on the type.

The declaration Foo f(0); is illegal, because there is no type named Foo. Perhaps you were thinking of

auto f = Foo(0);

but that is not allowed either, because the compiler doesn't know what scope to search in (there are infinite potential types with a constructor named Foo and, with specialization, possibly more than one with a constructor Foo(int))

The usual method to do this is with a factory helper function:

auto f = make_foo(0);

where the factory function's return type depends on type deduction of its parameters.


You can imagine that the factory functions could be automatically generated in namespace scope and then the usual function overloading rules applied, but this runs into significant difficulty because there can be template arguments on both the type and the constructor itself. These could simply be concatenated, with the limitation that this would exclude class templates with variadic argument lists, because there would be no way to distinguish where the type parameters end and the function parameters begin.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
9

Foo is a class template, not a class. Its type always needs to be supplied in some way or another for a class to be generated with the correct types. You can't do Foo because Foo isn't a type, but Foo<int> is. It creates a class like this:

class Foo {
public:
  Foo( int t ) { }
};

If you only supplied Foo, the compiler wouldn't know how to generate the class. Foo<int> f(0) works because Foo<int> generates the class, substituting T with int. By the type you call the constructor, the compiler already knows that the constructor is accepting an int.

David G
  • 94,763
  • 41
  • 167
  • 253
  • 1
    Well done, reminding people that a template is not a type. (I originally used "+1" instead of the first two words, but apparently that's not allowed) – Pete Becker Apr 16 '15 at 16:35
5

The name of the class you want to instantiate is Foo<int> (as you indicate).

It is also possible to write Foo<short> f(0), or Foo<unsigned long> f(0), or Foo<Foo<double>*> f(0). In those cases, however, you don't expect the compiler to be able to guess the type if you write only Foo f(0).

One could imagine that a C++ could have been specified with rules to make some such guesses in certain ways (such as, the literal 0 implies type parameter int and no other), but then the language would be even more complicated than it is now and there would be additional ways for people to make programming errors. Actually writing what you mean in a declaration like this seems like not too much to ask.

Edit: After posting this, I noticed in another answer that there is a proposal to make such a feature of C++, indeed as one could imagine.

David K
  • 3,147
  • 2
  • 13
  • 19
  • If I changed the instantiation to `int i = 0; Foo f( 0 );` The the compiler should have all the information it needs to instantiate `Foo` and call its contructor. Based on the answers above however, I can see why the compiler gets to `Foo` and does not know what to do with it and immediately reports an error. – Greg Wilbur Apr 16 '15 at 15:56
  • Sorry, I meant `int i = 0; Foo f( i );`. And I agree on the point that it would be tricky to implement, I just wanted to get a better idea toward the why. – Greg Wilbur Apr 16 '15 at 16:07
  • @wibs Thanks for the clarification, and I'm replacing my previous comment accordingly. The idea to infer `Foo f(0)` from `Foo f(i)` or even `Foo f(0)` is not _unreasonable_ (see the proposed change to the language mentioned elsewhere), and I might even be persuaded eventually that it's a good idea. The point of my answer really is just to suggest why it was also reasonable that it has not (yet) been added to the language specification. – David K Apr 16 '15 at 16:12