模板专业化与别名模板推导的区别

Sat*_*rnu 10 c++ templates template-meta-programming c++11 template-argument-deduction

在以下情况下,我难以理解推论的工作原理:

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)
{
}
Run Code Online (Sandbox Code Playgroud)

以下是测试代码:

A<int, 5> a1;
doSomething(a1); // This does not compile
doSomething<5>(a1); // This compiles
Run Code Online (Sandbox Code Playgroud)

为什么在这种情况下不推导a1?

如果改用以下方式修改A:

template<class Category, Category code>
struct A
{ };
Run Code Online (Sandbox Code Playgroud)

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

[edit]与混合别名和模板专业化相关的问题

Sto*_*ica 9

为什么在这种情况下不推导a1?

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

template<class Category, Category code>
using A = typename AHelper<Category, code>::type;
Run Code Online (Sandbox Code Playgroud)

要推论code,编译器将需要推导左侧的内容::,这是一个非推论上下文。如果模板参数推导显示为作用域解析运算符左侧的参数,则模板推论甚至不会尝试推导。

并非没有道理,这是一个不可推论的背景。请记住,模板可能是专门的。我可以添加以下内容:

template<Category code>
struct AHelper<int, code>
{
    using type = BImpl<code>; // My own class!
};
Run Code Online (Sandbox Code Playgroud)

编译器将需要查看整个程序中的所有代码,并尝试所有类型,以确保不会发生任何恶意事情,以确保a1确实与as匹配typename AHelper<Category, code>::type。太难了 因此,通过元功能进行的映射仅是单向路。您不能要求编译器从目标类型推断出源类型(或非类型参数)。