键入别名和模板模板参数推断

时间:2018-03-18 07:06:14

标签: 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;

现在定义一个类型别名

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>>被视为模板模板参数,但不在Matched<Alias>==true中。我发现这有点愚蠢,因为我认为类型别名作为类型的函数,我想与它们一起工作。现在,与类型相比,类型别名被视为二等公民,这使得难以以通用方式使用它们,例如组合或转换它们。

可能的出路:

1.更改扣除规则,以便将类型别名检测为模板模板参数。这将使using

2.在模板声明中使用template<template<typename> using T, typename T> bool Matched<F<T>> = true; ,如下所示:

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

问题:

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

作为旁注:类似的问题是变量模板。为什么我们不能写?

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

编辑(接受答案后):

我对类型演绎感到困惑。当我们在辅助类中存储类型别名

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

我们有一个功能

foo(Helper<Alias>{})

我们可以致电Alias。 Isn&#t; t onNavigationStateChange={(prevState, newState) => { // your code to determine screen }) &#34;推断&#34;在函数调用中?或者这不叫做类型扣除?

1 个答案:

答案 0 :(得分:4)

是的,那是故意的。正如你所说,别名模板确实是一个二等公民&#34;。首先,别名模板不能专门化,这是一个真正的大提示。

现在,他们的等级较低&#34;在你的例子中显而易见的是关于[temp.alias]/2

  

template-id 引用别名的特化时   模板,它相当于获得的关联类型   将 template-arguments 替换为 template-parameters   在别名模板的 type-id 中。 [注意:别名模板名称   永远不会推断出来。 - 结束说明]

以上意思是,当您撰写#!python2 x = [[1, ["cat", "dog"]], [2, ["dog", "mouse", "elephant"]], [3, ["mouse", "giraffe"]]] new_lst = [] for sublst in x: for subsublst in sublst[1]: if not any(subsublst in sublst for sublst in new_lst): new_lst.append([subsublst]) # nested list # new_lst.append(subsublst) # a list of strings print new_lst ''' [['cat'], ['dog'], ['mouse'], ['elephant'], ['giraffe']] ''' 时,由于Matched<Alias<int>>指的是别名模板的特化,它等同于直接Alias<int> 1}}。并且很明显为什么它与专用变量模板不匹配。

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