模板特化和别名模板推导区别

Template specialization and alias template deduction difference

我很难理解演绎在以下情况下的工作原理:

template<class Category, Category code>
struct AImpl
{ };

template<class Category, Category code>
struct AHelper
{
    using type = AImpl<Category, code>;
};

template<class Category, Category code>
using A = typename AHelper<Category, code>::type;

template<int code>
void doSomething(A<int, code> object)
{
}

测试代码如下:

A<int, 5> a1;
doSomething(a1); // This does not compile
doSomething<5>(a1); // This compiles

为什么在这个上下文中没有推导a1?

如果您改为按以下方式修改 A:

template<class Category, Category code>
struct A
{ };

两者都有效。有人知道为什么吗?

[编辑] 链接到

的问题

Why a1 is not deduced in this context?

因为doSomething的模板参数出现在非推导上下文中。别名模板几乎完全代表它的别名。而你的定义如下:

template<class Category, Category code>
using A = typename AHelper<Category, code>::type;

要推导 code,编译器需要推导 :: 左侧的某些内容,这是一个非推导的上下文。如果它作为范围解析运算符左侧的参数出现,则模板参数推导甚至不会尝试推导某些内容。

这不是没有原因的,这是一个未推导的上下文。请记住,模板可能是专门的。我可以添加这个:

template<Category code>
struct AHelper<int, code>
{
    using type = BImpl<code>; // My own class!
};

编译器需要查看整个程序中的所有代码并尝试所有类型以确保没有恶意发生,从而确定 a1 确实与 typename AHelper<Category, code>::type 匹配.那是棘手的。因此元函数的映射只是单行道。您不能要求编译器从目标类型推断出源类型(或非类型参数)。