13

The following code generates a compile error in Xcode:

template <typename T>
struct Foo
{
    Foo(T Value)
    {
    }
};

int main()
{
    Foo MyFoo(123);
    return 0;
}

error: missing template arguments before 'MyFoo'

Changing Foo MyFoo(123); to Foo<int> MyFoo(123); fixes the issue, but shouldn't the compiler be able to figure out the appropriate datatype?

Is this a compiler bug, or am I misunderstanding implicit template parameters?

Maxpm
  • 24,113
  • 33
  • 111
  • 170

7 Answers7

13

The constructor could in theory infer the type of the object it is constructing, but the statement:

Foo MyFoo(123);

Is allocating temporary space for MyFoo and must know the fully-qualified type of MyFoo in order to know how much space is needed.

If you want to avoid typing (i.e. with fingers) the name of a particularly complex template, consider using a typedef:

typedef std::map<int, std::string> StringMap;

Or in C++0x you could use the auto keyword to have the compiler use type inference--though many will argue that leads to less readable and more error-prone code, myself among them. ;p

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • 6
    if it could infer the type, it could infer the space. – Matthieu M. Feb 09 '11 at 16:23
  • 6
    It can infer the type for the call to the constructor, but not for the storage space. If you define a variable as simply `Foo`, can it hold both `Foo` and `Foo`? Or does it always know it's secretly a `Foo` in its heart of hearts? If the variable were `const` then it could be implemented, since the value could not be reassigned, but then we'd have different lexical rules for `const T` vs `T` and great havoc would ensue. – Jonathan Grynspan Feb 09 '11 at 18:57
  • 1
    "typing (i.e with fingers)" is a gem :D – Adam.Er8 Oct 27 '19 at 09:49
8

compiler can figure out template parameter type only for templated functions, not for classes/structs

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • 3
    After all, there is a reason for the function `std::make_pair(T t, U u)` even though we already have the class `std::pair`. – Max Lybbert Feb 09 '11 at 16:20
2

In C++11 you can use decltype:

int myint = 123;
Foo<decltype(myint)> MyFoo(myint);
Riot
  • 15,723
  • 4
  • 60
  • 67
2

It's not a bug, it's non-existing feature. You have to fully specify class/structure template arguments during instantiation, always, the types are not inferred as they can be for function templates.

Reinderien
  • 11,755
  • 5
  • 49
  • 77
Palmik
  • 2,675
  • 16
  • 13
2

Compiler can deduce the template argument such case:

template<typename T>
void fun(T param)
{
    //code...
}

fun(100);    //T is deduced as int;
fun(100.0);  //T is deduced as double
fun(100.0f); //T is deduced as float

Foo<int> foo(100);
fun(foo);    //T is deduced as Foo<int>;

Foo<char> bar('A');
fun(bar);    //T is deduced as Foo<char>;

Actually template argument deduction is a huge topic. Read this article at ACCU:

The C++ Template Argument Deduction

Nawaz
  • 353,942
  • 115
  • 666
  • 851
2

What you are trying to do now works in C++ 17. Template parameters can be inferred in C++ 17.

template <typename T>
struct Foo
{
    Foo(T Value)
    {
    }
};

int main()
{
    Foo a(123);
    Foo b = 123;
    Foo c {123};
    return 0;
}
0

It makes a lot of sense it is like this, as Foo is not a class, only Foo<T> where T is a type.

In C++0x you can use auto, and you can create a function to make you a Foo, let's call it foo (lower case f). Then you would do

template<typename T> Foo<T> foo(int x)
{
  return Foo<T>(x);
}

auto myFoo = foo(55);
CashCow
  • 30,981
  • 5
  • 61
  • 92