About type inference for function templates

I use the function read to read an integer from stdin in the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <cstdio>

int read()
{
    int x = 0, f = 1;
    char ch = getchar();

    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int a, b;

int main()
{
    a = read();
    b = read();
    printf("%d\n", a + b);
}


It works normally. for example, if I input
114 514
, it produces
628
.

I want to let the function read read different types of integers (int, long long, etc.). Therefore, I write another piece of code using template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <cstdio>

template<class T>
T read()
{
    T x = 0, f = 1;
    char ch = getchar();

    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int a, b;

int main()
{
    a = read();
    b = read();
    printf("%d\n", a + b);
}


However, the compiler does not know the type represented by T, so the compilation cannot continue.

This is the error message generated by the compiler:


main.cpp: In function ‘int main()’:
main.cpp:24:14: error: no matching function for call to ‘read()’
   24 |     a = read();
      |              ^
main.cpp:4:3: note: candidate: ‘template<class T> T read()’
    4 | T read()
      |   ^~~~
main.cpp:4:3: note:   template argument deduction/substitution failed:
main.cpp:24:14: note:   couldn’t deduce template parameter ‘T’
   24 |     a = read();
      |              ^
main.cpp:25:14: error: no matching function for call to ‘read()’
   25 |     b = read();
      |              ^
main.cpp:4:3: note: candidate: ‘template<class T> T read()’
    4 | T read()
      |   ^~~~
main.cpp:4:3: note:   template argument deduction/substitution failed:
main.cpp:25:14: note:   couldn’t deduce template parameter ‘T’
   25 |     b = read();
      |              ^


I must write a = read<int>(); to read an integer.

Is there any way that can let the compiler automatically infer the type of a function template?
I use the function read to read an integer from stdin


Why? What's wrong with using stream extraction?

At compile time, the type of T must be known - which isn't inferred from the return type. You can however specify a default type if none is specified. Eg:

 
template<class T = int>


You can also do this:

 
a = read<decltype(a)>();


which uses the defined type of a as the type T.

You can also use auto for the variable. Eg:

1
2
auto a {read<long long>()};
auto i {read()};    // Assuming default template type specified 

Last edited on
With C++20 it is possible to get a bit of narrowing for parameters with a single type when using the <concepts> library by specifying a core language concept.

https://en.cppreference.com/w/cpp/concepts

For example you want integers only you could define your function as

auto max(std::integral auto x) { ... }

That could lead to some rather weird looking code since bool and char are both considered integral types. Perfectly legal, compilable code that works.

https://en.cppreference.com/w/cpp/concepts/integral

C++20 also introduced the "abbreviated function templates" feature. The above function is an example of one.

https://en.cppreference.com/w/cpp/language/function_template
Topic archived. No new replies allowed.