了解类型特征的体系结构

Understanding the architecture of type traits

本文关键字:体系结构 特征 类型 了解      更新时间:2023-10-16

根据我目前对type traits的理解,我想以最好的方式表达这个问题。

我的理解是,type traits中的所有模板类都继承自std::integral_constant,它包装了模板类已实例化的value及其相应的type的表示。此外,type traits中的常见模板类继承自std::integral_constant的帮助程序别名模板,即std::bool_constant,如它们的定义所示。

例如,在std::is_arithmetic的情况下,从std::integral_constant继承的value的类型是bool,这意味着模板类继承自std::bool_constant。此外,模板类std::is_arithmetic还从其底层基继承operator bool,该基库应该将对象转换为bool并(可能将其作为value中的结果返回)。

所以我的问题是:整个语义是如何联系在一起的?

std::is_arithmetic<2>实例的情况下,如果假设基数是std::integral_constant<typename T, T v>的,T变得int,并且v变得2。但是,由于type traits中的大多数常见模板类显然都是从std::bool_constant继承而来的,因此基类实例化首先是如何发生的?继承operator bool返回的值(可能的)转换为truefalse的底层逻辑是什么?

以下是integral_constant的可能实现:

template <typename T, T v>
struct integral_constant {
static constexpr T value = v;
using value_type = T;
using type = integral_constant; // the current instantiation
constexpr   operator T() const noexcept { return v; }
constexpr T operator()() const noexcept { return v; }
};

因此,有三种方法可以访问integral_constant(或其派生类)的值:

  • integral_constant<T, v>::value,其中使用静态数据成员value;

  • integral_constant<T, v>{}(),其中operator()在类型为integral_constant<T, v>的对象上调用;和

  • integral_constant<T, v>{}隐式转换为布尔值。

bool_constant只是一个别名模板:

template <bool B>
using bool_constant = integral_constant<bool, B>;
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;

现在让我们考虑一个实际的类型特征。 以is_same为例:

template <typename T, typename U>
struct is_same :false_type {};
template <typename T>
struct is_same<T, T> :true_type {};

如果类型相同,则从true_type派生(即integral_constant<bool, true>),否则派生false_type(即integral_constant<bool, false>)。 因此,您可以通过上述三种方式使用它:

static_assert(is_same<int, int>::value); // use ::value member
static_assert(is_same<int, int>{}());    // use operator()
static_assert(is_same<int, int>{});      // use operator bool

还可以使用::type提取基础integral_constant基类,::value_type提取值的类型:

static_assert(is_same<true_type, is_same<int, int>::type>{});
static_assert(is_same<bool, is_same<int, int>::value_type>{});

在 C++17 中,我们还有另一种访问值的方法:is_same_v<int, int>

static_assert(is_same_v<int, int>);      // since C++17

这不是魔法;is_same_v只是一个定义为相应值的变量模板:

template <typename T, typename U>
inline constexpr bool is_same_v = is_same<T, U>::value;