将别名模板匹配为模板参数

Matching alias template as template argument

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

考虑以下代码:

#include <type_traits>
template<template<class...> class T, class... U>
struct is_specialization_of : std::false_type{};
template<template<class...> class T, class... U>
struct is_specialization_of<T, T<U...>> : std::true_type{};
template<class T, class U = int>
struct test{};
// (1) ok
static_assert(is_specialization_of<test, test<int>>::value, "1");
template<class T>
using alias = test<T>;
// (2) fails
static_assert(is_specialization_of<alias, alias<int>>::value, "2");
int main()
{
}

为什么(2(,即使用别名模板的static_assert,失败?

模板参数扣除过程(2(中的扣除过程与(1(中的一个不同?

这是CWG问题1286。问题是:aliastest等效吗?曾经在[temp.type]中有一个示例,该示例表明yz在这里具有相同的类型:

template<template<class> class TT> struct X { };
template<class> struct Y { };
template<class T> using Z = Y<T>;
X<Y> y;
X<Z> z;

该示例被纠正为CWG缺陷1244的一部分 - 正确地表明,[temp.alias]中没有措辞实际上指定别名模板等于它们的模板。那里唯一的措辞是指别名模板专业的等效性:

当A template-id 是指别名模板的专业化时,它等同于通过替换其 template-arguments arguments /em>用于 parameters 在别名模板的 type-id 中。

意图显然是yz do 在此示例中具有相同的类型,这意味着ZY实际上是等效的。但是,除非并且直到采用决议中的措辞,否则不是。今天,aliastest不是等效的,但是alias<int>test<int> 。这意味着is_specialization_of<alias, alias<int>>is_specialization_of<alias, test<int>>,其中aliastest中是唯一的,它与您的部分专业化不匹配,因此是false_type

此外,即使在#1286中采用了措辞,testalias中仍然不是等效,因为test采用两个模板参数,并且别名采用一个模板参数。分辨率措辞中的示例模仿了您的示例,并在此处阐明了目的:
template<typename T, U = T> struct A;
// ...
template<typename V>   
  using D = A<V>;      // not equivalent to A:
                       // different number of parameters

我认为没有模板参数列表的别名模板的名称不等于相关类型的名称。因为标准仅指定了一种情况:

14.5.7别名模板[temp.alias]

  1. 当模板-ID指的专业化模板时,它等效于相关类型 通过替换其模板 - arguments将模板参数替换为Alias的类型ID 模板。[注意:别名模板名称永远不会推导。—端注]

这很好:

static_assert(is_specialization_of<test, alias<int>>::value, "2");