首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C++那些事之SFINAE

如您所见,在序列化过程中,很容易检查对象是否具有属性并查询该属性的类型。在我们的例子中,它允许我们使用serialize方法(如果可用),否则返回到更通用的方法str。功能强大,不是吗?...您可以使用此解决方案的变体对类型进行大量测试(测试成员,子类型...),我建议您更多地搜索SFINAE技巧。...我带给您难题的最后一部分,称为enable_if。 如您所见,我们可以使用enable if根据编译时表达式触发替换失败。...在c++ 11中,constexpr有很多规则,只能使用一小部VIEs(非常重要的表达式)表达式(没有循环……)!...在decltype中,将评估所有表达式,但仅将最后一个表达式视为该类型。序列化不需要任何更改,减去了STL中现在提供了enable_if函数的事实。

2.2K20

现代C++之SFINAE

如您所见,在序列化过程中,很容易检查对象是否具有属性并查询该属性的类型。在我们的例子中,它允许我们使用serialize方法(如果可用),否则返回到更通用的方法str。功能强大,不是吗?...您可以使用此解决方案的变体对类型进行大量测试(测试成员,子类型...),我建议您更多地搜索SFINAE技巧。...我带给您难题的最后一部分,称为enable_if。 如您所见,我们可以使用enable if根据编译时表达式触发替换失败。...在c++ 11中,constexpr有很多规则,只能使用一小部VIEs(非常重要的表达式)表达式(没有循环……)!...在decltype中,将评估所有表达式,但仅将最后一个表达式视为该类型。序列化不需要任何更改,减去了STL中现在提供了enable_if函数的事实。

3K20
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【C++11】消除重复, 提升代码质量---type_tratis

    : false D: true 1.4 获取可调用对象返回类型的traits std::result_of可以在编译器获取可调对象的返回类型,帮助解决编码过程中如下问题: 函数入参为模板参数,不能直接确定函数返回类型...; 通过decltype推导函数返回类型时可读性差问题; 使用后置推导类型时,如果没有构造函数导致编译报错的问题; std::result_of原型如下: template <class Fn, class...main() { Fun(1); return 0; } 程序运行为最终会匹配到第二个模板函数,但是在实际的匹配过程中,当匹配到void Fun(T*)时用整数对T*进行替换是错误的,但是编译器会继续匹配...,直到匹配到void Fun(T)后执行正确的函数,这种规则就是SFINAE;反之,如果一个模板函数都没有匹配到,则编译器会报如下错误: error: no matching function for...使用std::enable_if可以实现一个强大的重载机制,充分利用可以减少或者消除圈的复杂度。如:根据不同的数据基本类型转换为string进行输出。

    1.7K10

    C++11:unique_ptr 自己定义类似make_shared的make_unique模板函数

    C++11中的智能指针分为共享型的shared_ptr和独占型的unique_ptr,C++11提供了make_shared函数来创建shared_ptr指针,使用起来更方便,有了make_shared...用到了名为std::enable_if的type_traits,它类似一个if语句,判断ZERO,当ZERO为true时编译器选择第一个版本的函数,反之选择第二个。...enable_if是C++11头文件type_traits>中的一个类,关于enable_if的用法详细说明参见: class template type_traits>std::enable_if...其实我是写完上面的代码在VS2015下编译时,报了个错, 我这才发现,VS2015已经提供了make_unique 以下是来自VS2015的头文件中make_unique...的实现代码,代码中创建普通对象和数组对象的函数名都是make_unique,与我写的版本不一样,而且微软的版本中也没有区分是否在初始化数组,一律初始化为0。

    1.2K20

    性能优化利器之constexpr

    从概念上理解的话,constexpr即常量表达式,重点在表达式字段,用于指定变量或函数可以在常量表达式中使用,可以(或者说一定)在编译时求值的表达式,而const则为了约束变量的访问控制,表示运行时不可以直接被修改...自C++17起,引入了if constexpr语句,在本节中,将借助SFINAE 和 std::enable_if来实现一个简单的Square功能,最后借助if constexpr对代码进行优化(如果对...为了解决这个问题,我们尝试引入std::enable_if操作,如下: template typename std::enable_ifstd::is_arithmetic类型,则调用第一个,否则调用第二个,完整代码如下: #include type_traits> template typename std::enable_if的if语句就能解决上面的问题,且比使用std::enable_if方式更为优雅和符合阅读习惯,进而提高代码的可阅读性。

    42210

    std::shared_ptr 的线程安全性 & 在多线程中的使用注意事项

    我们在讨论 std::shared_ptr 线程安全时,讨论的是什么? 在讨论之前,我们先理清楚这样的一个简单但却容易混淆的逻辑。...std::shared_ptr 是个类模版,无法孤立存在的,因此实际使用中,我们都是使用他的具体模版类。...这里使用 std::shared_ptr 来举例,我们讨论的时候,其实上是在讨论 std::shared_ptr 的线程安全性,并不是 SomeType 的线程安全性。...() 函数是否线程安全,这里显示是非线程安全的,因为对 some_value 的操作没有加锁,也没有使用 atomic 类型,多线程访问就出现未定义行为(UB) std::shared_ptr 线程安全性...ThreadSanitizer: reported 4 warnings Terminated due to signal: ABORT TRAP (6) 从错误信息中可以清晰地看到出现的数据竞争,在

    2.7K10

    能向入口函数传入多个参数的 QueueUserWorkItem

    std::tuple; using std::mem_fn; using std::result_of; using std::enable_if; using std::true_type; using..._Func 时绑定到之上的对象的指针,参见 示例1.2; 4、QueueUserWorkItemEx 在完成参数拷贝后返回,而非向线程池的任务队列投递任务后立即返回;原因是 若在目标线程拷贝参数前返回可能导致目标线程使用已被销毁的对象...这可能会导致线程池依托任务队列建立的可 伸缩性失效,具体解决方法请参考注意事项第1条。 注意: 1、当Args参数包中参数数量不为零时会引起等待;等待线程池中线程调用_Func 前的参数拷贝完成。...建议的解决方法是使用参数数量为零的lambda,并捕获所需参数,让拷贝提前发生。 2、若用户试图嵌套调用 QueueUserWorkItemEx ,将得到一个“IO未决”错误。...5、参数包中包含的某些对象的初始化过程可能会创建某些依赖于线程的内部对象(如 Windows 的窗口对象), 对于此情况,我的建议是不要作为参数传递,或改用 std::async 。

    1.3K20

    实际工程中的 C++ 模板

    这里的 lib::void_t 是什么?std::void_t 是 C++ 17 之后才在 STL 中提供的模板,它很简单也非常有用,功能是将任意的类型序列映射到 void 上,也就是忽略掉这些类型。...>::type; 这里使用 void_t 将多个类型声明忽略掉以适应 templatevoid> 中的第二个类型参数: decltype(std::begin...所以我们只能使用 adapter 模式解决这个问题: struct MyDataBlobAdapter { using key_type = ...; void SetKey(key_type...这个 IsLegalDb 的实现也用到了 SFINAE,大致可以实现为这样: templatevoid> struct IsLegalDb: std::false_type...第一是我们这里的类型在 3 和 5 处继承了 std::true_type 和 std::false_type,这两个类型可以认为是类型级别的 true 和 false,在头文件 type_traits

    2.1K20

    opencl:cl::make_kernel的进化

    调用都要有上面两个动作,概括起来就是 在执行kernel之前,如果kernel参数中有指针类型或imag类型的参数,需要将参数在主机端对应的cl::Memory类型(其子类包括cl::Image,cl:...中的所有变长参数类型进行识别, * 对于memory_cl类型的参数,根据需要在kernel执行前上传数据到设备, * 并在kernel执行后根据需要下载输出数据到主机 * 模板中的N参数,用于调试时知道哪个参数出错...* * */ // 参数ARG为非memory_cl类型时直接返回,啥也不做 template typename std::enable_if<!...,const ARG & arg){} // 参数ARG是memory_cl类型,时根据需要上传数据 template typename std::enable_if...;//递归处理其他参数 } // 参数ARG为非memory_cl类型时,为空函数,啥也不做直接返回 template typename std::enable_if

    1.4K20

    C++11 元编程(meta-programming)判断T是否有==操作符

    基本的原理与文中的差不多,利用SFINAE原则,通过返回类型后置来推断表达式的类型,推断的过程中利用declval,它可以获取类型的右值引用,以便来调用==操作符,这个过程是在编译期完成的。...test(...)函数,它的返回类型为void。...test(...); enum{value=std::is_same(0)), bool>::value}; }; 在上面代码中,推导test(int)返回类型的表达式是由执行...对于基本数据类型(比如int),因为没有成员函数,所以第二种方式对于基本类型返回的肯定是false.无法用这种方式判断基本数据类型是否有==操作符,只适用于class类型。...下面是完整的代码 #include #include type_traits> using namespace std; struct test_classA{ int

    31930

    C++ enable_shared_from_this 具体实现

    C++ 中使用 std::shared_ptr 智能指针不当有可能会造成循环引用,因为 std::shared_ptr 内部是基于引用计数来实现的, 当引用计数为 0 时,就会释放内部持有的裸指针。...但是当 a 持有 b, b 也持有 a 时,相当于 a 和 b 的引用计数都至少为 1,因此得不到释放,RAII 此时也无能为力。这时就需要使用 weak_ptr 来打破循环引用。...可以看到,在构造 DataFetch 的时候, 我们使用了 shared_from_this() 作为参数: data_fetcher_ = std::make_shared(..._NOEXCEPT {} 对于第一个问题,就是 enable_if 起的作用: enable_if类型T>::type 的意思是说,如果bool值为true,enable_if 返回的就是第二个模版参数...类型T, 如果为false,返回空(不是void,而是什么也没有) 那么看下: enable_if<is_convertible<_OrigPtr*, const enable_shared_from_this

    1.1K30

    Chapter 5: Rvalue References, Move Semantics, PF

    ,再重新转发到标签分发函数中,再次分发 logAndAdd(nameFromIdx(idx)); } 上面的std::true_type和std::false_type就是标签,我们可以利用它们来强制选择我们希望调用的重载函数...对于用户自定义的类型而言,他们是继承自自身的,也就是说std::is_base_of会返回为true,但是当T是内建类型时,就会返回为false。...没有显式支持移动操作或不满足编译器自动生成移动操作的类型 并非所有支持移动的标准库容器都会受益于移动操作 对于把内容存储在堆内存中,而自身只保存指向该堆内存指针的容器类型来说,移动操作仅仅是拷贝这个指针到新的容器中...这种情况下出错的类型有: 编译器无法推导出一个类型:只要参数中有一个及以上无法推导出类型,就无法编译 编译器推到出错误的类型:要么是推导出来的类型使得无法编译,要么是推到出来的类型在重载函数情况下匹配到错误的函数调用...同样,在将MinVals传递到模板函数fwd中时,这个模板参数是一个引用,它本质上和指针是一样,只不过是一个会自动解引用的指针,那么在编译该函数时就需要对MinVals进行取地址,而MinVals此时并没有定义

    5.1K40

    灵魂拷问std::enable_shared_from_this,揭秘实现原理

    灵魂拷问std::enable_shared_from_this,揭秘实现原理 引言 在C++编程中,使用智能指针是一种安全管理对象生命周期的方式。...为了解决这个问题,C++引入了std::enable_shared_from_this类,本文将深入探讨其基础知识、使用案例以及内部实现。...多个 shared_ptr 实例通过共享的 控制块 结构来控制对象的生命周期。 当使用原始指针构造或初始化 shared_ptr 时,会创建一个新的控制块。...在可能的情况下,尽量使用 std::make_shared(或 std::allocate_shared)来减少发生此错误的可能性。...但首先,像下面这样尝试使用 this 指针创建 shared_ptr 不会起作用,原因如上所述: struct Foo { std::shared_ptr getSelfPtr() {

    2.6K10

    C++11 JNI开发中RAII的应用(一)--制作基础工具

    第二个场景以在jni代码(native code)中创建java 对象数组为例说明,在jni代码中创建大量本地引用而不显式释放可能会导致out of memory。...反正我不想在写代码时总掂记着引用有没有释放的问题。...struct时返回resource的地址 //这里->操作符使用了函数模板实现,用到了is_pointer和is_class两个type_trait来判断T的类型, //如果T不是指针,也不是class.../struct,则没有->操作符实现 同样为了方便调用,还增加了支持类型转换的模板函数_get(),允许指定返回类型调用_get(),比如 raii_obj...._get(),调用_get()时将raii_obj中的对象转成jstring类型 /* 根据 _T类型不同选择不同的函数模板 */ template<typename

    40010
    领券