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

Type aliases and template template argument deduction

本文关键字:参数 别名 类型      更新时间:2023-10-16

问题:

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

例:

我们将使用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>>。我觉得这有点愚蠢,因为我认为类型别名是类型的函数,我想使用它们。现在,与类型相比,类型别名被视为二等公民,这使得难以以通用方式使用它们,例如组合或转换它们。

可能的出路:

1.更改扣除规则,以便将类型别名检测为模板模板参数。这将使Matched<Alias>==true.

2.允许在模板声明中使用using,如下所示:

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

问题:

这种行为是故意的吗?这是疏忽吗?是否注意到了这一点,是否会在 c++ 的未来版本中修复?


作为旁注:类似的问题也存在于变量模板中。为什么我们不能写?

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

编辑(接受答案后):

我对类型推断感到非常困惑。当我们将类型别名存储在帮助程序类中时

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

我们有一个功能

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

我们可以称之为foo(Helper<Alias>{}).函数调用中不是Alias"推导"出来的吗?或者这不叫类型演绎?

是的,这是故意的。正如您所说,别名模板确实有点"二等公民"。首先,别名模板不能专门化,这是一个真正的重要提示。

现在,在您的示例中,它们的"较低等级"都是关于 [temp.alias]/2:

模板 ID引用别名的专用化时 模板,它相当于由 将其模板参数替换为别名模板的类型ID中的模板参数。[ 注意:别名模板名称 从未被推断出来。— 尾注 ]

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

这不是疏忽,也不会被修复。别名模板旨在为更复杂的模板表达式提供简写。而且您不希望调用错误的重载,或者实例化错误的模板专用化,因为您使用了速记而不是整个复杂表达式。