确定每次使用哪种模板专业结构

Deciding which template specialization structure to use each time

本文关键字:结构      更新时间:2023-10-16

我在 C++中有以下声明:

template<class T1, class T2> struct canAssign {
    enum { result = false };
};
template<class T1> struct canAssign<T1,T1> {
    enum { result = true };
};

我有以下电话(A扩展了B(:

canAssign<A,A>::result;
canAssign<B,A>::result;
canAssign<B*,A*>::result;

我知道它使用template specialization功能,但我似乎不明白它如何决定每次选择哪一个?

编辑:我知道输出应该是什么:

true
false
false

我的问题是编译器如何选择合适的编译器?我需要在脑海中考虑哪种算法/方法/方法,以了解哪一种将被称为

可能的继承在这里不计数。

所以你有:

canAssign<A, A>::result;   // true  T1=A, T2=A as T1=T2, use specialization
canAssign<B, A>::result;   // false T1=B, T2=A
canAssign<B*, A*>::result; // false T1=B*, T2=A*

我的问题是编译器如何选择合适的编译器?我需要在脑海中考虑哪种算法/方法/方法,以了解哪一种将被称为

该算法在您针对的特定标准的[temp.class.spec.match]部分(以及相关的算法(中进行了描述。

我的问题是编译器如何选择合适的编译器?我需要在脑海中考虑哪种算法/方法/方法,以了解哪一种将被称为

编译器选择最专业的版本(如果有歧义选择最专业的可用,并出现错误(。

当一个版本比另一个版本更专业

1(模板参数的所有匹配,对于更专业的匹配也是较少的专业

2(,并且有较少专业化的匹配,而不是更专业的

在您的情况下,您有两个版本的canAssign:主要的和专业。

显然,专业化比主要版本更专业,因此,如果是

canAssign<A,A>::result;

机器人版本匹配,因此编译器选择专业化。

在其他情况下

canAssign<B,A>::result;
canAssign<B*,A*>::result;

仅主要版本匹配,因此编译器选择主版本。

一个更好地解释这一点的示例:假设您有一个带有两个专业的模板foo

template <typename, typename, typename>
struct foo 
 { };
template <typename A, typename B>
struct foo<A, A, B>
 { };
template <typename A>
struct foo<A, A, A>
 { };

第二个专业化比拳头更专业。

实际上

1(所有集合参数(必然所有等于(匹配第二个模板参数,必须匹配第一个(第一个和第二个等于(

2(至少存在一组模板参数( intintlong(,与第一个相匹配,但不匹配第二个。

so:

1(第二个专业化比第一个专业化更专业

2(第一个专业化比主版本更专业

so

  • foo<int, int, int>匹配所有版本,因此编译器选择第二个专业化

  • foo<int, int, long>匹配主版本和第一个专业化,因此编译器选择第一个专业化

  • foo<int, long, int>仅匹配主版本,因此编译器选择主版本。

这是一种模式匹配。

这将是一个恰好的故事。它与标准不完全匹配,但我发现它会产生良好的直觉。

template<class T1, class T2> struct canAssign {
  enum { result = false };
};

这是主要的规格。它定义了模板签名-<class T1, class T2>定义的两个类。如果没有其他匹配的话,它也是实例化的。

template<class T1> struct canAssign<T1,T1> {
  enum { result = true };
};

这是次要专业。在这里,<class T1>的目的不同。它引入了变量以匹配模式,而不是参数。

参数在<T1,T1>部分中。编译器与传递的参数匹配<T1,T1>

"推论上下文"中的任何参数都是独立匹配的。因此,如果您通过<A,B>,则与T1=A匹配,然后T1=B。这是不一致的;专业不匹配。如果通过<A,A>,则与T1=AT1=A匹配。这是一致的。

当您进行<T1*,T1*>时,事情变得更加典型。然后,如果您通过<A,A>,它将尝试T1*=A并失败;但是,如果通过<A*,A*>,它将以T1*=A*开头,然后剥离*并获取T1=A,然后再次对第二个参数进行操作。

未建立的上下文是不同的。当您具有不循环的上下文(例如std::enable_if_t<some_bool, T1>(时,该参数未完成模式匹配。取而代之的是,其他参数与模式匹配,然后将专业模板变量取代。如果结果类型与参数完全匹配,则它会通过。否则会失败。

最后一个位是订购。如果两个次要的专业经历通过,则严格"更专业"的胜利。如果两者都不具体专业化,则两者都不会获胜。更专业的规则很复杂;直观的想法是,一个专业化是否可以符合另一个案例,但反之亦然,严格匹配的一个专业化是更专业的。