使用 typename 参数时,模板参数 deduction/substitution 失败

Template argument deduction/substitution failed, when using typename argument

我有以下代码,它定义了一个模板结构 W,它导出一个类型 T,该类型基于 W 的模板参数:

#include <iostream>
using namespace std;

template <unsigned N>
struct Y {};

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

然后我定义了这个查看此类型的模板函数T:

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

这里的问题是,如果我尝试使用导出为 T 的类型之一从 main 调用此函数,它不会编译。例如,如果我写

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

我收到一个编译器错误

template argument deduction/substitution failed:

couldn't deduce template parameter

这是怎么回事?

C++ 编译器无法解决这个问题的原因与模板专业化有关。例如,假设您像这样特化 W 结构模板:

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

现在,假设您调用 foo,传入一个 Y<0> 作为参数。编译器应该推导出什么作为 N 的数值?它可以为零,因为 W<0>T 定义为 Y<0>。但它也可以很容易地成为 137,因为 W<137> 也将 T 定义为 Y<0>

更一般地说,C++ 永远不会尝试根据 内部 之一将模板参数的类型推断为 outer 模板类型,正是出于上述原因。