美文网首页
【C++Template】检查一系列参数类型异同

【C++Template】检查一系列参数类型异同

作者: crossous | 来源:发表于2020-08-14 15:52 被阅读0次

前言

  自己在学习中的收获以及研究出来的写法。

一、检查一系列参数中所有类型都相同

  这个利用C++17的fold expression特性很容易就能写出来。
  假如有个可变模版参数的方法test:

template <typename T, typename... Ts>
void test() {
    std::cout << std::conjunction_v<std::is_same<T, Ts>...>;
}

int main() {
    test<int, int, int, int>();//true
    test<int, int, float, int>();//false
}

  std::conjunction是连接模版运算符,它的每个模版参数是std::std::bool_constant类型(类比做bool类型),
  std::std::bool_constant下有两个using:

template<bool _Val>
using bool_constant = integral_constant<bool, _Val>;

using true_type = bool_constant<true>;
using false_type = bool_constant<false>;

  std::conjunction的每个模版实参类似:

std::conjunction<std::true_type, std::true_type, std::false_type, ...>

  相当于对所有bool做与(&&)运算,而最后运算出的值也是true_typefalse_type
  如果单单如此,我们要让参数包的所有类型展开类似:

conjunction<is_same<T0, T1>, is_same<T1, T2>, is_same<T2, T3>, ...>

  就得写一套递归程序解析参数包,但C++17的fold expression能帮助我们把参数包平铺开来。

二、检查让让参数包所有参数类型全不相等

  这不是上个问题的直接取反,例如参数包[int, int, float, double, int],用上个问题的调用能得到false,取反得到true,但里面还有很多int重复了。
  问题的复杂度来了,比较所有类型是否相同的复杂度是O(n),只要把1和2比,2和3比,有一个不同就可以得到false。
  而是否全不相同,至少要让所有类型两两比较,遇到相同的返回false,复杂度是O(N^2)
  不过在此之前先完善下设施,标准库自带了std::is_same<Ty1, Ty2>,但没有类似is_not_some的功能,好在功能简单,只要仿照,很容易写出来:

template<class _Ty1, class _Ty2>
struct is_not_same : std::true_type {};
//偏特化,假如两个类型相同,匹配第二个
template<class _Ty1>
struct is_not_same<_Ty1, _Ty1> : std::false_type {};
//方便取值(true或false)的
template<class _Ty, class _Uty>
_INLINE_VAR constexpr bool is_not_same_v = is_not_same<_Ty, _Uty>::value;

  接下来继续想,假如我们有一系列参数包[A, B, C, D, E],我希望能按照如下步骤进行解析:
1.先取出前两个参数,参数列表大致为:A, B, [C, D, E]
比较A和B,记做compare<A, B>
假如符合我们的想法,则将参数传递:
(compare<A, B>=true), A, C, [D, E]
否则向下传递:
(compare<A, B>=false), A, [C, D, E]
并结束递归
2.(compare<A, C>=true), A, D, [E]
3.(compare<A, D>=true), A, E, []
4.(compare<A, E>=true), A, [] 在此时结束递归
  此时我们写出初始的包装类型:

template<
    template <class _Ty1, class _Ty2> class _Compare,//比较器
    class _First,//第一个参数
    class _Second,//第二个参数
    class... Rest //其他参数
>
//将比较器传递下去
//将比较结果传递下去
//将第一个参数传递下去
//将除了第二个参数外的其他参数传递下去
struct FirstCompareToOther
    : _CompareStruct<_Compare, _Compare<_First, _Second>::value, 
        _First, Rest...>::type
{};

  然后给上述的结构增加递归比较设施_CompareStruct

//主模版
//当参数包Rest为空时结束递归
//或上一次比较数据Value为false时结束递归
template<
    template <class A, class B> class _Compare,
    bool Value,
    class _First,
    class... Rest
>
struct _CompareStruct {
    using type = std::bool_constant<Value>;
};

//偏特化模版,当上一次比较为true时继续比较
template<
    template <class A, class B> class _Compare,
    class _First,
    class _Next,
    class... Rest
>
struct _CompareStruct<_Compare, true, _First, _Next, Rest...>
{
    using type = typename _CompareStruct<_Compare, _Compare<_First, _Next>::value, _First, Rest...>::type;
};

  现在通过比较器,可以将第一个参数与其他参数进行比较:

std::cout << FirstCompareToOther<std::is_same, int, int, int, int, int>::value;
//true

std::cout << FirstCompareToOther<std::is_same, float, int, int, int, int>::value;
//false

  用我们自己写的is_not_same也是可以的:

//false
std::cout << FirstCompareToOther< is_not_same, int, int, double, int, double> ::value;

  如我们所想存在三个int,不能称之为全不相同。但上述外码还不能做到比较全部的功能,假如我们有如下调用:

//true
std::cout << FirstCompareToOther < is_not_same, int, float, double, float, double> ::value;

  int和后面的参数都不相同,但又两个float,两个double,因此还要继续编写代码,让每个参数都与后面所有的参数进行比较。
  我们写下最后的代码:

template <class _First, class _Second, class... Rest>
struct all_is_not_same
    : std::conjunction<FirstCompareToOther<is_not_same, _First, _Second, Rest...>, all_is_not_same<_Second, Rest...>>::type
{};

template <class _First, class _Second>
struct all_is_not_same<_First, _Second>
    : is_not_same<_First, _Second>::type
{};

//false
std::cout << all_is_not_same<int, float, double, float, char>::value;

相关文章

  • 【C++Template】检查一系列参数类型异同

    前言   自己在学习中的收获以及研究出来的写法。 一、检查一系列参数中所有类型都相同   这个利用C++17的fo...

  • javaSE_day13_泛型

    泛型:参数化数据类型;类,方法 ,构造器,接口 好处:编译器 进行类型检查; 泛型类:类名 <类型参数> 类型参数...

  • No matching function for call to

    检查一下传的参数和参数类型

  • Python的学习-3

    1.Python的内置函数会检查出参数类型错误。比如数据类型错误检查的参数是isinstance。 2.Pytho...

  • 利用装饰器强制函数上的类型检查

    场景:对函数参数进行强制类型检查。

  • Python:函数参数类型检查

    有一个很经典的笑话: 三个月之前,只有我和上帝知道这代码是干什么的。现在,只有上帝知道了。 在Python中,不知...

  • Python 函数

    参数检查 使用了isinstance函数进行数据类型的检查 默认参数 例: 如果不写3默认函数power_n的参数为2

  • python--用装饰器做参数检查

    编写自定义python函数后,一般有一个参数检查过程,检查输入的参数是否是定义的类型,参数检查可以避免一些明显错误...

  • 编程语言中 泛型的意义和作用

    ●类型的参数化,可以把类型像方法的参数那样传递。意义非凡。●在编译期间对类型进行检查以提高类型安全,减少运行时由于...

  • 第二天:Python函数

    函数 isinstance(x, int):检查参数类型callable(object):检查一个对象是否是可调用...

网友评论

      本文标题:【C++Template】检查一系列参数类型异同

      本文链接:https://www.haomeiwen.com/subject/aduwdktx.html