Why can't constructors deduce template arguments?

C++

C++ Problem Overview


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.)

C++ Solutions


Solution 1 - C++

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

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGreg WilburView Question on Stackoverflow
Solution 1 - C++Sebastian RedlView Answer on Stackoverflow
Solution 2 - C++Ben VoigtView Answer on Stackoverflow
Solution 3 - C++David GView Answer on Stackoverflow
Solution 4 - C++David KView Answer on Stackoverflow