了解类型特征的体系结构

时间:2019-07-24 05:14:46

标签: c++ c++17 typetraits

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

我的理解是type traits中的所有模板类都继承自std::integral_constant,它包装了实例化模板类的value及其对应的{{ 1}}。此外,type中的通用模板类继承自type traits的辅助别名模板,即std::integral_constant,如其定义所示。

例如,在std::bool_constant的情况下,从std::is_arithmetic继承的value的类型为std::integral_constant,这意味着模板类从{{1} }。此外,模板类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_constanttrue的基础逻辑是什么?

1 个答案:

答案 0 :(得分:6)

这是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。

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;