0

I use some type trait like techniques to wrap the pointer and reference to improve its readability. I use ptr<T> to represent T*, and lref<T> to represent T&. I wrote codes below.

template <typename T>
struct ptr_impl {
  using type = T*;
};
template <typename T>
using ptr = typename ptr_impl<T>::type;

template <typename T>
struct lref_impl {
  using type = T&;
};
template <typename T>
using lref = typename lref_impl<T>::type;

It seemed to work fine until I wrote such a function

template <typename T, size_t N>
size_t CalculateArraySize(lref<T[N]>) {
  return sizeof(T) * N;
}

I got compiler errors when I tried to pass a parameter like this

int arr[100];
lref<int[100]> p = arr;
CalculateArraySize(p);

Compiler(g++10) output err messages as below.

In function 'int main()':
/testcodes/test.cpp:122:23: error: no matching function for call to 'CalculateArraySize(int [100])'
  122 |   CalculateArraySize(p);
      |                       ^
/testcodes/test.cpp:115:8: note: candidate: 'template<class T, long unsigned int N> size_t CalculateArraySize(lref<T [N]>)'
  115 | size_t CalculateArraySize(lref<T[N]>) {
      |        ^~~~~~~~~~~~~~~~~~
/testcodes/test.cpp:115:8: note:   template argument deduction/substitution failed:
/testcodes/test.cpp:122:23: note:   couldn't deduce template parameter 'T'
  122 |   CalculateArraySize(p);
      |                       ^

and I also try to overload another function without template, it works.

size_t CalculateArraySize(lref<int[100]>) {
  return sizeof(int) * 100;
}

So why compiler can not deduce template parameter in such case?

youtao guo
  • 73
  • 1
  • 4
  • I tried even `CalculateArraySize(static_cast>(p));`. However error message alos showed `error: no matching function for call to 'CalculateArraySize(int [100])' 128 | CalculateArraySize(static_cast>(p));` – youtao guo Sep 09 '21 at 14:16
  • related/dupe: https://stackoverflow.com/questions/25245453/what-is-a-nondeduced-context – NathanOliver Sep 09 '21 at 14:27

1 Answers1

0

Your lref<T> is only an alias for a nested type lref_impl<T>::type, and types cannot be deduced from their nested types.

For example, if you have

template <typename T>
struct Identity { using type = T };

then the following will not be compiled:

template <typename T>
void f(typename Identity<T>::type t){}

void g(){f(1);}
Eugene
  • 6,194
  • 1
  • 20
  • 31