false_type 和 true_type的使用

文章介绍了如何使用C++模板元编程创建一个has_limit结构,该结构用于检测类型是否具有特定成员。它类似于enable_if,通过类模板偏特化来判断类型特征。示例代码展示了如何检测一个类型是否有limit成员,并在实际应用场景中,如CUB框架中,进行类型检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用背景

假如有个函数模板参数,假如必须是类型A,一般咋写呢?

template<int N, typename A>
A func(A* in)
{
	return in[N];
}
func<3>(in);

这里有个问题,就是假如传入的是B类型的in,好像也能运行,但是我只要这个模板支持A类型咋办?我们知道C++中类是有偏特化的,而模板函数没有,C++提供了enable_if和true_type两种解决方案。

C++20

true_type
template <typename T> 
struct is_limit: std::false_type {};

template <>
struct is_limit<Limit> : std::true_type {};
/*
template <typename T>
struct is_limit< Limit<T> > : std::true_type {};

template <int N>
struct is_limit< Limit<N> > : std::true_type {};
*/
template <typename T>
concept LimitLike = is_limit<T>::value;

template<int N, typename A, Limitlike>
void test();
test<1, float, Limit>();//ok
test<1, float, float>();//error

思想也比较简单,当你传入Limit时候,LimitLike这个模板类会接受一个Limit的类型参数,也就是这里的T是Limit,所以会选择true_type这个实现,如果传入其他类型,这里会走到false type类型,当编译器检测到模板参数里出现false_type的话就会编译报错。

enable_if

说实话,我觉得enable这种更加好理解,用concept很多人不了解或者编译器都不支持

template<int N, typename A, typename T, enable_if_t<is_limit<T>, bool> = true>
void test();
test<1, float, Limit>();//ok
test<1, float, float>();//error

简单解释一下,enable_if_t一旦条件是false的话,由于只有一个模板函数可以实例化,所以就会报出编译错误,而如果成功的话又必须搞一个type,这里用一个bool类型并且提供一个默认初始值true.

对于C++17之前没有concept的话使用如下:

模板

比葫芦画瓢先看看怎么使用,理解起来其实不难,但是基本模式要记住

template <typename T>
struct void_type {
  using type = void;
};

template <typename T, typename = void>
struct has_limit: public std::false_type {};
//
template <typename T>
struct has_limit<T, typename void_type<typename T::limit>::type>
    : public std::true_type {};

参考:https://blog.csdn.net/sunny_98_98/article/details/116136331

使用

一般哪里会有这个使用需求呢???struct has_limit有点类似于实现了一个enable_if的功能,通过类模板的偏特化特性, 下面是一个小demo,但是一般不这样直接使用。

struct Limit
{
        using limit = int;
};

int main()
{
        std::cout<<has_limit<int>::value<<std::endl; //0
        std::cout<<has_limit<Limit>::value<<std::endl; //1
}

实际上使用:

template<typename T, bool dummy = has_limit<T>::value>
struct Real
{
};

template<typename T>
struct Real<T, false>
{
};

int main()
{
        std::cout<<has_limit<int>::value<<std::endl; //0
        std::cout<<has_limit<Limit>::value<<std::endl; //1
}

具体在一些cub框架里使用, 有一点小出入但是大体没区别,代码在cub/block/radix_rank_sort_operations.cuh

template <class... >
using void_t = void;

template <class T, class = void>
struct is_fundamental_type
{
  static constexpr bool value = false;
};

template <class T>
struct is_fundamental_type<T, void_t<typename Traits<T>::UnsignedBits>>
{
  static constexpr bool value = true;
};

template <class T, bool = is_fundamental_type<T>::value>
struct traits_t
{
  using bit_ordered_type              = typename Traits<T>::UnsignedBits;
}

template <class T>
struct traits_t<T, false /* is_fundamental */>
{
  using bit_ordered_type              = T;
  using bit_ordered_conversion_policy = custom_bit_conversion_policy_t;
}

总结

我自己觉得就是实现一个enable_if的作用,但是看起来花里胡哨,不知道理解的是不是有问题,希望大佬指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值