I've got this template function:
template<typename T>
void f(const T* t1, const T* t2) {}
Then in main():
int i = 1;
f(&i, NULL);
It doesn't compile, saying candidate template ignored: could not match 'const T *' against 'int'
If change it into:
int i = 1;
f(&i, nullptr); // same error!
I know I can fix it like this, specifying the type info:
int i = 1;
f<int>(&i, NULL);
Ok, it gets compiled.
But isn't it that, c++ compiler could do type deduction for us : so that we can call template functions without specifying all the type information?
Seems NULL
/nullptr
here is an unusual case for template.
My question: is there a way to go without f<int>
in each place, just f
, when there's NULL
/nullptr
?
Thanks.
The compiler uses both parameter to deduce T
, and because neither nullptr
nor NULL
are of type int*
there is a conflict between the types deduced from &i
and from nullptr
/ NULL
.
Note that nullptr
is of type nullptr_t
. It can be converted to any other pointer type, but nullptr_t
is a distinct type.
Since C++20 you can use std::type_identity
to establish a non-deduced context:
#include <type_traits>
template<typename T>
void f(const T* t1, const std::type_identity_t<T>* t2) {}
int main() {
const int* x;
f(x,nullptr); // calls f<int>
}
The second parameter will then not be used to deduce T
. Whether this is really what you want depends on details of f
. Before C++20, the trait is rather simple to write yourself (see possible implementation).