type_traits有优先顺序吗



我对SFINAE很陌生,想知道如果多个std::enable_if_t<true, std::is_...<T>>最终应用于T,编译器是否会选择哪个模板。

如本例所示:

template<typename T, typename = void>
class Thing {
// Thing A
};
template<typename T>
class Thing<T, std::enable_if_t<true, std::is_scalar<T>> {
// Thing B
};
template<typename T>
class Thing<T, std::enable_if_t<true, std::is_float<T>> {
// Thing C
};
template<typename T>
class Thing<T, std::enable_if_t<true, std::is_signed<T>> {
// Thing D
};
template<>
class Thing<float> {
// Thing E
};

int main(){
Thing<float> x;   // what order would the compiler try out?
}

我认为它会尽量选择";特定的";模板专业化,所以E在前,A在后,但这就是我所确信的。我不知道它将如何从BCD中消除歧义,也不知道如果我需要控制消除歧义的过程,如何组合T的多个条件。

还要回答一个问题:不,这种优先级不存在。enable_if的操作虽然聪明,但要么失败,要么成功。更重要的是,替换发生在任何潜在的实例化相互比较之前。这种比较的规则很复杂,但在您的示例中,它确实可以归结为选择最专业的选项,使用以下排名:

  1. 事物A是主要的(最不专业的(模板
  2. 事物B、C和D同样专业,但比A更专业
  3. E是最专业的

因此将选择E。B、 必须考虑C和D,因为它们的条件都被评估为true,并且它们同样专门化,因为它们每个都有单个类型参数T。由于一个有效的程序每次使用一个名称都必须有一个明确的匹配,因此如果从示例中删除Thing E,就会出现编译器错误。

现在,可以通过使用具有更合适(组合(条件的enable_if来消除B、C和D的歧义,并且歧义问题不会通过使用概念而神奇地消失。然而,您可以直接将概念与模板参数一起使用,例如:

#include <concepts>
template<typename T>
class Thing {};         // Thing A
template<std::integral T>
class Thing<T> {};      // Thing B
template<std::signed_integral T>
class Thing<T> {};      // Thing C
template<std::floating_point T>
class Thing<T> {};      // Thing D
template<>
class Thing<float> {};  // Thing E
int main() {
Thing<float>  E;
Thing<double> D;
Thing<int>    C;
Thing<bool>   B;
Thing<void>   A;
}

这只是一个简短的例子,但我认为概念是对通用C++的重大改进,应该把它们作为模板来教授和学习。它们现在得到了广泛的支持,所以如果您碰巧有一个较旧的编译器,您可以随时在编译器资源管理器上试用它们。

相关内容

  • 没有找到相关文章

最新更新