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

tom*_*tom 4 c++ templates typedef type-deduction

问题:

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

例子:

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

template <typename T>
bool Matched = false;

template <template <typename> typename F, typename T>
bool Matched<F<T>> = true;
Run Code Online (Sandbox Code Playgroud)

现在定义一个类型别名

template<typename T>
using Alias = std::tuple<T,T>;
Run Code Online (Sandbox Code Playgroud)

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

template<template<typename> typename F>
using ApplyInt = F<int>;
Run Code Online (Sandbox Code Playgroud)

然后ApplyInt<Alias>工作正常。

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

可能的出路:

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

2.允许using在模板声明中使用这样的:

template<template<typename> using T, typename T>
bool Matched<F<T>> = true;
Run Code Online (Sandbox Code Playgroud)

题:

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


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

template <template<typename> auto Var>
auto VarForInt = Var<int>;
Run Code Online (Sandbox Code Playgroud)

编辑(接受答案后):

我真的对类型推导感到困惑。当我们在辅助类中存储类型别名时

template<template<typename> typename F>
struct Helper{};
Run Code Online (Sandbox Code Playgroud)

我们有一个功能

template<template<typename> typename F>
void foo(Helper<F>){}
Run Code Online (Sandbox Code Playgroud)

我们可以打电话foo(Helper<Alias>{})Alias函数调用中不是“推导”出来的吗?或者这不叫类型推导?

Sto*_*ica 6

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

现在,在您的示例中,他们的“低级”完全是关于[temp.alias]/2

模板id是指一个别名模板的专业化,它相当于通过其置换得到的相关联的类型的模板的参数模板参数类型ID别名模板。[?注意:永远不会推导出别名模板名称。?—?尾注?]

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

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