C++11 —— 统计 tuple 中指定数据类型的数量

问题背景

??在实现可变参数列表中的类型统计功能前,我们先看看下面代码中的需求场景:

/**
 * @struct x_selector_t< size_t >
 * @brief  协助 make_task() 接口的特化选择功能的辅助类。
 */
template< size_t >
struct x_selector_t
{

};

/**
 * @brief xtuple 参数列表中未包含指定数据类型的时候,创建 x_task_A_t 对象。
 */
template< typename... _Args >
x_task_t * make_task(const x_selector_t< 0 > &, std::tuple< _Args... > && xtuple)
{
    using _Tuple = typename std::tuple< _Args... >;
    return (new x_task_A_t(std::forward< _Tuple >(xtuple)));
}

/**
 * @brief xtuple 参数列表中包含指定数据类型 1 个的时候,创建 x_task_B_t 对象。
 */
template< typename... _Args >
x_task_t * make_task(const x_selector_t< 1 > &, std::tuple< _Args... > && xtuple)
{
    using _Tuple = typename std::tuple< _Args... >;
    return (new x_task_B_t(std::forward< _Tuple >(xtuple)));
}

/**
 * @brief xtuple 参数列表中包含指定数据类型 2 个的时候,创建 x_task_C_t 对象。
 */
template< typename... _Args >
x_task_t * make_task(const x_selector_t< 2 > &, std::tuple< _Args... > && xtuple)
{
    using _Tuple = typename std::tuple< _Args... >;
    return (new x_task_C_t(std::forward< _Tuple >(xtuple)));
}

??上面的代码中,x_task_A_t, x_task_B_t, x_task_C_t 都是 x_task_t 的派生类,按照上面已经提供的三个 make_task() 接口,我们能不能只提供一个接口(如下面的代码所示),就可自动选择这三个接口之一创建 x_task_t 对象呢?当然可以,只要我们解决 “怎么统计 tuple 中指定数据类型的数量” 这个问题就能办到。

/**
 * @brief 自动统计 _Ty 数据类型在 xtuple 参数列表中的数量,
 *        然后选择对应的 make_task() 接口,创建 x_task_t 对象。
 */
template< typename _Ty, typename... _Args >
x_task_t * create_task(const x_selector_t< 2 > &, std::tuple< _Args... > && xtuple)
{
    using _Tuple = typename std::tuple< _Args... >;

    constexpr size_t const xty_count = ...; // 统计 _Ty 在 _Args... 参数列表中的数量

    // 当前只有三种方式创建对象,增加编译期的断言判断
    static_assert(xty_count < 3, "There are currently only three ways to create x_task_t!");

    // 使用 x_selector_t< xty_count >() 特化对象,进行接口选择
    return make_task(x_selector_t< xty_count >(), std::forward< _Tuple >(xtuple)));
}

解决办法

??为解决可变参数列表种的类型统计问题,我们可以利用 C++11 的可变参数模板类的自动推导的特性,实现这一功能,请看下面代码所给出了解决的方案:


/** X_type_count 的前置声明 */
template< typename _Fy, typename... _Ty >
struct X_type_count;

/**
 * @struct X_type_count< _Fy, _Hy, _Ty... >
 * @brief  递归的数据类型统计类。
 */
template< typename _Fy, typename _Hy, typename... _Ty >
struct X_type_count< _Fy, _Hy, _Ty... >
{
    enum { value = (int)(std::is_same< _Fy, _Hy >::value) + X_type_count< _Fy, _Ty... >::value };
};

/**
 * @struct X_type_count< _Fy >
 * @brief  终止递归的数据类型统计类。
 */
template< typename _Fy >
struct X_type_count< _Fy >
{
    enum { value = 0 };
};

/**
 * @brief 统计 tuple 对象内某个数据类型的数量。
 */
template< typename _Fy, typename... _Ty >
constexpr size_t X_tuple_type_count(const std::tuple< _Ty... > &)
{
    return X_type_count< _Fy, _Ty... >::value;
}

??细看 X_type_count< _Fy, _Hy, _Ty... >::value 值的实现方式,我们用标准库提供的 std::is_same< _Fy, _Hy >::value 进行类型判断,将判断结果的 bool 值强制转换为为整数(0 或 1),然后累加到 value 中;下一步再以递归方式累加 X_type_count< _Fy, _Ty... >::value 的值,最后逐步地统计到整个可变参数列表中指定类型的数量。

??完整的测试代码如下:

#include <type_traits>
#include <tuple>
#include <iostream>

////////////////////////////////////////////////////////////////////////////////

/** X_type_count 的前置声明 */
template< typename _Fy, typename... _Ty >
struct X_type_count;

/**
 * @struct X_type_count< _Fy, _Hy, _Ty... >
 * @brief  递归的数据类型统计类。
 */
template< typename _Fy, typename _Hy, typename... _Ty >
struct X_type_count< _Fy, _Hy, _Ty... >
{
    enum { value = (int)(std::is_same< _Fy, _Hy >::value) + X_type_count< _Fy, _Ty... >::value };
};

/**
 * @struct X_type_count< _Fy >
 * @brief  终止递归的数据类型统计类。
 */
template< typename _Fy >
struct X_type_count< _Fy >
{
    enum { value = 0 };
};

/**
 * @brief 统计 tuple 对象内某个数据类型的数量。
 */
template< typename _Fy, typename... _Ty >
constexpr size_t X_tuple_type_count(const std::tuple< _Ty... > &)
{
    return X_type_count< _Fy, _Ty... >::value;
}

////////////////////////////////////////////////////////////////////////////////

int main(int argc, char * argv[])
{
    std::cout << "X_type_count< int, _Ty... > : "
              << X_type_count< int, int, int, char, char, double >::value << std::endl;

    using _XTuple = std::tuple< int, int, int, char, char, double >;
    std::cout << "tuple type : std::tuple< int, int, int, char, char, double > " << std::endl;
    std::cout << "X_tuple_type_count< int    > : " << X_tuple_type_count< int    >(_XTuple{}) << std::endl;
    std::cout << "X_tuple_type_count< char   > : " << X_tuple_type_count< char   >(_XTuple{}) << std::endl;
    std::cout << "X_tuple_type_count< double > : " << X_tuple_type_count< double >(_XTuple{}) << std::endl;
    std::cout << "X_tuple_type_count< float  > : " << X_tuple_type_count< float  >(_XTuple{}) << std::endl;
    std::cout << "X_tuple_type_count< void * > : " << X_tuple_type_count< void * >(_XTuple{}) << std::endl;

    return 0;
}

??输出结果如下:

X_type_count< int, _Ty... > : 2
tuple type : std::tuple< int, int, int, char, char, double >
X_tuple_type_count< int    > : 3
X_tuple_type_count< char   > : 2
X_tuple_type_count< double > : 1
X_tuple_type_count< float  > : 0
X_tuple_type_count< void * > : 0

原文地址:https://www.cnblogs.com/Gaaagaa/p/12130416.html

时间: 2024-11-06 10:49:38

C++11 —— 统计 tuple 中指定数据类型的数量的相关文章

C++11 —— 获取 tuple 参数列表中指定数据类型的索引位置

1. 问题背景 ??在 C++11 的标准中,我们可以通过 std::get< Index >(tuple) (以常量整数值为索引号)操作 tuple 中的参数,而到了 C++14 之后的标准,新增了 std::get< Type >(tuple) (以数据类型为索引)的方式操作 tuple 中的参数.那么,若只是在 C++11 标准中,是否有办法使用 以数据类型为索引 的方式操作 tuple 中的参数呢? 2. 解决办法 ??解决上面所提到的问题,其本质上,就是要解决 如何获取

C++11 —— 判断 tuple 中是否包含某个数据类型

??如标题所提到的,这个问题也让我烦恼了一会,前两天在某个论坛上(现在找不到出处了)看到有如下代码的解决办法,非常巧妙,在此整理并记录出来做备忘. #include <type_traits> #include <tuple> #include <iostream> /** * @struct X_check * @brief 协助 X_tuple_has_type() 进行类型检查. */ template< bool... > struct X_type

统计字符串中指定字符的个数

输入一个字符串和一个字符,统计这个字符在字符串中出现的次数 输入格式: 输入2行.第1行是字符串,第2行是要查找的字符. 输出格式: 字符出现的次数 输入样例: abcdefgabcdefg a 输出样例: 2 a=input() b=input() def CountAa(s): return s.lower().count(b) if __name__ == "__main__": s = a print(CountAa(s)) 原文地址:https://www.cnblogs.c

MySQL 中的数据类型介绍

MySQL 中的数据类型介绍 标签: mysql数据类型mysql全部数据类型mysql字段类型mysql数据存储mysql 2016-04-29 20:24 53643人阅读 评论(11) 收藏 举报  分类: 服务器及软件---MySQL数据库(4)  版权声明:http://blog.csdn.net/anxpp 目录(?)[+] 据我统计,MySQL支持39种(按可使用的类型字段统计,即同义词也作多个)数据类型.下面的介绍可能在非常古老的MySQL版本中不适用. 转载请注明出处:http

Python中的数据类型

Python中的数据类型 目录1.字符串2.布尔类型3.整数4.浮点数5.数字6.列表7.元组8.字典9.日期 1.字符串(http://www.cnblogs.com/yjd_hycf_space/p/6846284.html)1.1.如何在Python中使用字符串a.使用单引号(')用单引号括起来表示字符串,例如:str='this is string';print str; b.使用双引号(")双引号中的字符串与单引号中的字符串用法完全相同,例如:str="this is str

typeScript中的数据类型

/* typeScript中的数据类型 typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要给我们提供了以下数据类型 布尔类型(boolean) 数字类型(number) 字符串类型(string) 数组类型(array) 元组类型(tuple) 枚举类型(enum) 任意类型(any) null 和 undefined void类型 never类型 */ //布尔类型(boolean) /* es5的写法 (正确写法) ts中(错误写法) v

MySQL中各种数据类型的长度及在开发中如何选择

接触MySQL这个数据库大概快要两年了,不过由于没有特别深入系统的去学习,大多也是停留在一知半解的状态.今天在工作中刚好碰到了表设计的问题,顺便写篇博客,把MySQL中数据类型和字段类型选择这方面给弄清楚. MySQL中的数据类型大体分为三大类,数值类型,时间日期类型以及字符串类型.下面将对这三种类型进行详细的介绍. 一.数值类型 MySQL 支持所有标准SQL 中的数值类型,其中包括严格数值类型(INTEGER.SMALLINT.DECIMAL 和NUMERIC),以及近似数值数据类型(FLO

(转载)你好,C++(11)如何用string数据类型表示一串文字?根据初始值自动推断数据类型的auto关键字(C++ 11)

你好,C++(11)如何用string数据类型表示一串文字?根据初始值自动推断数据类型的auto关键字(C++ 11) 3.5.2  字符串类型 使用char类型的变量我们可以表示单个字符,那么,我们又该如何表示拥有多个字符的字符串呢? 我们注意到,一个字符串是由多个字符串连起来形成的.很自然地,一种最简单直接的方法就是利用数组(一种数据组织管理方式,它将多个相同类型的数据元素组织起来,形成一个数据序列以便于访问.更多可以参考后文3.6小节对数组的介绍)来保存一个字符串中的各个字符,最后用一个特

你好,C++(11)如何用string数据类型表示一串文字?根据初始值自动推断数据类型的auto关键字(C++ 11)

3.5.2  字符串类型 使用char类型的变量我们可以表示单个字符,那么,我们又该如何表示拥有多个字符的字符串呢? 我们注意到,一个字符串是由多个字符串连起来形成的.很自然地,一种最简单直接的方法就是利用数组(一种数据组织管理方式,它将多个相同类型的数据元素组织起来,形成一个数据序列以便于访问.更多可以参考后文3.6小节对数组的介绍)来保存一个字符串中的各个字符,最后用一个特殊字符'\0'表示字符串的结束,以此来将多个char类型的字符数据串联成字符串.例如: // 定义一个字符数组,用以保存