类型别名和模板模板参数推导

Type aliases and template template argument deduction

问题:

我注意到在使用类型别名时,模板推导过程中存在一点不一致。特别是类型别名可以用作模板模板参数,但不能推导为一个。

示例:

我们将使用 Matched<Type> 来查看 Type 是否是模板类型的实例。

template <typename T>
bool Matched = false;

template <template <typename> typename F, typename T>
bool Matched<F<T>> = true;

现在定义一个类型别名

template<typename T>
using Alias = std::tuple<T,T>;

我的问题是 Matched<Alias<int>>==false。但是 Alias 可以用作模板模板参数,例如:

template<template<typename> typename F>
using ApplyInt = F<int>;

然后 ApplyInt<Alias> 工作正常。

回顾一下,在 ApplyInt<Alias> 中被视为模板模板参数,但在 Matched<Alias<int>> 中则不然。我觉得这有点愚蠢,因为我认为类型别名是类型上的函数,我想使用它们。现在,与类型相比,类型别名被视为第二 class 公民,这使得很难以通用方式使用它们,例如组合或转换它们。

可能的出路:

1.Change 推导规则,这样类型别名被检测为模板模板参数。这将使 Matched<Alias>==true.

2.Allow using 在模板声明中的用法如下:

template<template<typename> using T, typename T>
bool Matched<F<T>> = true;

问题:

这种行为是故意的吗?这是疏忽吗?这是否已被注意到并且会在未来的 c++ 版本中得到修复?


附带说明:类似的问题是变量模板。为什么我们不能写?

template <template<typename> auto Var>
auto VarForInt = Var<int>;

编辑(接受答案后):

我对类型推导感到非常困惑。当我们在助手中存储类型别名时 class

template<template<typename> typename F>
struct Helper{};

我们有一个函数

template<template<typename> typename F>
void foo(Helper<F>){}

我们可以调用foo(Helper<Alias>{})Alias "deduced" 不是在函数调用中吗?或者这不叫类型推导?

是的,那是故意的。正如您所说,别名模板确实有点像 "second class citizen"。首先,不能专门化别名模板,这是一个非常重要的提示。

现在,他们的 "lower grade" 在您的示例中很明显是关于 [temp.alias]/2:

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template. [ Note: An alias template name is never deduced. — end note ]

上面的意思是,当你写Matched<Alias<int>>时,由于Alias<int>指的是别名模板的特化,它相当于直接Matched<std::tuple<int,int>>。很明显为什么它与专用变量模板不匹配。

这不是疏忽,也不会修复。别名模板可以为更复杂的模板表达式提供 shorthand。而且您不希望调用错误的重载,或者实例化错误的模板特化,因为您使用了 shorthand 而不是整个复杂表达式。