首页 > 编程语言 >c++ template std::void_t 是个啥

c++ template std::void_t 是个啥

时间:2022-10-24 16:25:08浏览次数:63  
标签:std 匹配 void member template foo type

源码

<type_traits>头文件里有void_t的定义

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

很简单,其实就是void,只不过可以传入模板参数,比如std::void_t<int, float, double>,但归根到底他还是void

有什么用

那他有啥用,看上去像是一段无用的程序
这里就用到SFINAE(Substitution failure is not an error)的知识了,我们分三步走

  • 先看这个问题: 下面有三种foo函数,称其为Foo0,Foo1,Foo2,请问 foo foo foo 分别匹配到了哪个函数?

    struct X {
      typedef int type;
    };
    
    struct Y {
      typedef int type2;
    };
    
    template <typename T> void foo(typename T::type);    // Foo0
    template <typename T> void foo(typename T::type2);   // Foo1
    template <typename T> void foo(T);                   // Foo2
    
    foo<X>(5);    // Foo0: Succeed, Foo1: Failed,  Foo2: Failed
    foo<Y>(10);   // Foo0: Failed,  Foo1: Succeed, Foo2: Failed
    foo<int>(15); // Foo0: Failed,  Foo1: Failed,  Foo2: Succeed
    

    对于foo,因为X有type,所以直接匹配到了Foo0
    对于foo,因为Y没有typ,所以匹配Foo0失败,尝试匹配下一个,Y有type2,成功匹配到了Foo1
    对于foo,因为int既没有type有没有type2,所以Foo0和Foo1都匹配失败,最终匹配到了Foo2
    看到了吧,虽然有的地方匹配失败了,但是编译器并不会直接报错,他会尝试去匹配其他的

  • 回到std::void_t,通过上一点可知,我们对他的定义应该更严谨 : 如果传进来的模板参数是正常的,那std::void_t就是void;但是如果传进来的模板产生了错误,std::void_t会产生匹配错误,编译器您去找别人吧...

  • 将 SFINAE 和 std::void_t 结合,我们可以得到任意类型的不同匹配分支

    // primary template handles types that have no nested ::type member:
    template< class, class = void >
    struct has_type_member : std::false_type { };
     
    // specialization recognizes types that do have a nested ::type member:
    template< class T >
    struct has_type_member<T, std::void_t<typename T::type>> : std::true_type { };
    
    auto f = has_type_member<float>::value; // false
    auto x = has_type_member<X>::value; // true
    auto y = has_type_member<Y>::value; // false
    

    对于has_type_member<float>,因为float没有type,所以第二个模板会匹配失败,编译器会认为现在的has_type_member<float>实际是has_type_member<float, void>(因为void是个默认参数),进而成功匹配第一个模板
    对于has_type_member<X>,因为X有type,第二个模板直接匹配成功,编译器就不会去尝试匹配has_type_member<float, void>
    这里std::void_t的作用,就是把传进来的各个类型进行一个检测,哦没错过了吧!诶不对传进来的有问题编译器你快过来看看!

标签:std,匹配,void,member,template,foo,type
From: https://www.cnblogs.com/miyanyan/p/16821794.html

相关文章

  • 使用WireShark分析使用RedisTemplate取不到值的问题
    现象:使用JavaRedis客户端将数据存放到Redis后,使用redisTemplate却不出来原因:JavaRedis客户端在将数据存放在Redis时,会对Key,Value,Field进行编码。从Redis中取数据时,如果......
  • TEMPLATE3. Permutations 排列
    TEMPLATE3.Permutations组合,可以乱序。所以,需要记录哪些数用过了。每次递归时,选用第一个没用过的数。注意回溯时清空标记。//TEMPLATE3.Permutations#include<bits......
  • JDBCTemplate_介绍和JDBCTemplate_快速入门
    JDBCTemplate_介绍:spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发步骤︰1.导入jar包2.创建dbcTemplate对象。依赖于数据源DatasourcejdbcTemplat......
  • Vue组件template中html代码自动补齐设置
    1、vscode设置==>扩展==>JSON==>在settings.json中编辑2、在最后}前添加如下代码保存文件即可//自动补全模板字符串"emmet.triggerExpansionOnTab":true,......
  • JDBCTemplate-执行DML语句和执行DQL语句
    JDBCTemplate-执行DML语句需求:定义成员变量 //1、获取JDBCTemplate对象privateJdbcTemplatetemplate=newJdbcTemplate(JDBCUtils.getDataSource());......
  • 关于ReadisTemplate的Api
    ValueOperations:简单K-V操作SetOperations:set类型数据操作ZSetOperations:zset类型数据操作HashOperations:针对map类型的数据操作ListOperations:针对list类型的数据操作......
  • 详解 RestTemplate 操作
    详解RestTemplate操作作为开发人员,我们经常关注于构建伟大的软件来解决业务问题。数据只是软件完成工作时要处理的原材料。但是如果你问一下业务人员,数据和软件谁更重要......
  • visual stdio使用
     现在转换使用visual stdio,因为很多和以前的快捷键不同,也不打算换了,这样可移动性应该更好吧。1、注释代码, 首先按下ctrl+k,然后再按下ctrl+c2、取消注释,首先按下ctrl......
  • JDBCTemplate-介绍和JDBCTemplate-快速入门
    JDBCTemplate-介绍SpringJDBCSpring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发步骤:1.导入jar包2.创建JDBCTemplate对象。依赖于......
  • ERROR: <bits/stdc++.h>, 'cstdalign' file not found, running C++17
    Modified ​​1year,1monthago​​Viewed 9ktimes4I'mtryingtorunapieceofcodein VisualStudioCode,onmacOSCatalina.Thecode:#include<bits/stdc+......