c++functiontemplatesparametersnullptr

c++: do we need to explicitly specify type info for template function, when using NULL/nullptr?


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.


Solution

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