2
votes

I have the following code, which defines a template struct W that exports a type T that's based on the template argument to W:

#include <iostream>
using namespace std;

template <unsigned N>
struct Y {};

template <unsigned N>
struct W {
  using T = Y<N>;
};

I then defined this template function that looks at this type T:

template <unsigned N>
void foo (const typename W<N>::T& in) {
  //--
}

The problem here is that if I try calling this function from main using one of the types exported as T, it doesn't compile. For example, if I write

int main() {
  Y<2> y;
  foo(y);
  return 0;
}

I get a compiler error that says

template argument deduction/substitution failed:

couldn't deduce template parameter

What's going on here?

1

1 Answers

1
votes

The reason that the C++ compiler can't figure this out has to do with template specialization. For example, suppose that you specialize the W struct template like this:

template <> struct W<137> {
    using T = Y<0>; // Not Y<137>
};

Now, suppose that you call foo, passing in a Y<0> as the argument. What should the compiler deduce as the numeric value of N? It could be zero, since W<0> defines T as Y<0>. But it could just as easily be 137, since W<137> defines T as Y<0> as well.

More generally, C++ will never try to deduce the type of a template argument to an outer template based on one of the inner types, for precisely the reason shown above.