Home > Net >  Why int[] cannot be converted to T*&?
Why int[] cannot be converted to T*&?

Time:09-02

template <class T>
void func(T*& a)
{

}

int main()
{
    int a[5];
    func(a); // <-- Error here: no matching function for call to ‘func(int [5])’

    return 0;
}

why int[] is not implicitly converted to int* so that it can match template functions?

CodePudding user response:

There is an implicit conversion from int[5] to int*, but an int[5] is not an int*. Thus there is no int* for the int*& parameter of func<int> to reference.

This situation is no different from trying to pass an int to a function expecting a float&. Just because an int can be implicitly converted to a float doesn't mean an int is a float. The exact same thing applies to int[5] and int*. Just because one can be implicitly converted to the other doesn't mean that they are the same thing.

CodePudding user response:

There are actually two issues. One is about how references work, and the other is about how templates work.

Let's examine them separately.

Consider these non-template functions:

void foo(int*&) {}
void bar(int* const &) {}
void baz(int*) {}

The second and third functions accept array arguments, but the first one does not. That's because arrays decay to temporary pointers. Non-const references don't bind to temporaries, but const references work just fine. The third function works just fine too because a temporary can be passed by value.

Now consider templates. If we turn the above functions into templates, only the third function works, the first two do not. Why is that?

That's because T* does not match int[5], so deduction fails in the first two cases. It does not fail in the third case because there is a special provision for it in the standard.

If P is not a reference type:

  • If A is an array type, the pointer type produced by the array-to-pointer standard conversion is used in place of A for type deduction; ...

So when the parameter type is T* (not a reference), int[5] is replaced with int*, and lo and behold,T* matches int*, so T can be deduced. But when the parameter is a reference, no such replacement is made.

CodePudding user response:

There are 2 things that are important here:

  1. Since the parameter a is a reference type, the passed argument is not passed by value. In other words, conversion like array to pointer decay will not happen for the passed argument.

  2. Since the parameter is a reference to a pointer to a T, the passed argument must be of a pointer type.

Now, lets apply this to your example:

By writing func(a), you're passing the argument a which is of array type int [5] by reference so that it will not decay to a pointer to int(int*). In other words, the parameter expects that you pass an argument of pointer type by reference but you're passing an array type by reference(so that there is no decay to pointer type) and hence the error.

  • Related