C++ 模板参数推断失败

C++ 模板参数推断失败,c++,templates,C++,Templates,我编写了以下代码,其中模板参数推断失败: template<int> struct num {}; template<int m> void match(num<2*m>) { } int main() { match(num<2>()); return 0; } 模板 结构num{}; 模板 无效匹配(num){ } int main() { 匹配(num()); 返回0; } 我凭直觉知道编译器无法推断出正确的m,但我想了解它失

我编写了以下代码,其中模板参数推断失败:

template<int>
struct num {};

template<int m>
void match(num<2*m>) {
}

int main()
{
  match(num<2>());
  return 0;
}
模板
结构num{};
模板
无效匹配(num){
}
int main()
{
匹配(num());
返回0;
}

我凭直觉知道编译器无法推断出正确的
m
,但我想了解它失败的理论基础。有人能解释一下吗?

好吧,你基本上是要求编译器为你解方程
2*m==2
,以便确定
匹配的模板参数
m
。在模板参数推导过程中,编译器不会求解方程,无论它们有多么简单和明确

14.8.2.4/14(C++03)、14.8.2.5/16(C++11)中的语言规范涵盖了您的情况,并有一个类似的示例

14如果在函数模板声明中使用非类型 模板参数,非类型模板参数用于 函数参数列表中的表达式,对应的 必须始终明确指定或推导模板参数 否则,类型扣减将始终失败 模板参数

模板类A{/*…*/};
模板g(A);
void k(){
A A;
g(a);//错误:表达式s+1的演绎失败
g(a);//好的
}

至于为什么会这样做。。。我认为很明显,在一般情况下,解一个数学方程的问题太复杂了。它还可能导致不明确的解决方案或不属于预期领域的解决方案。例如,对于
match(num())
,您希望编译器推断出什么?

不幸的是,这里甚至这里的最新草稿似乎没有该小节。但我相信你的话:)@keveman:我是从C++03复制的。在C++ 11中,等效部分是14.2.5/16.我们可能不希望编译器中有一个整数方程求解器,但是我很好奇这个问题是否在计算机科学术语中是固有的“不可判定”,还是C++语言设计者是出于实际的原因决定这么做的。简而言之,“这个简单的数学方程有没有一个解决方案,只需要几次运算”并不是一个编译器应该回答的问题。
template<int i> class A { /* ... */ };
template<short s> void g(A<s+1>);

void k() {
  A<1> a;
  g(a); //error: deduction fails for expression s+1
  g<0>(a); //OK
}