文章目录 一、编译时元编程引入 二、声明需要编译时处理的类 三、分析 Groovy 类的 AST 语法树 一、编译时元编程引入 ---- 在之前的 " 【Groovy】MOP 元对象协议与元编程 " 系列博客中..., 都是围绕 MetaClass 的 " 运行时元编程 " , 其在运行时才进行相关的元编程操作 , 如方法注入 , 方法委托等 ; 在编译时也可以进行元编程操作 ; 在 Java 和 Android...中 , 可以使用 注解处理器 AbstractProcessor 实现 APT 编译时技术 , 参考 【Android APT】 专栏 ; 在 Groovy 中实现的编译时技术 , 类似于 Java...中的编译时技术 ; 二、声明需要编译时处理的类 ---- 声明一个 Student 类 , 在其中定义成员变量和成员方法 ; 之后需要在编译时处理该类 ; class Student{ def...选项 , 分析上述 Student 类的 AST 语法树 ; 分析结果在 Groovy AST Browser 对话框中显示 ;
有人问:C语言为什么只需要include就能使用里面声明的函数?这是一个看起来非常简单的问题,但是很多初学者,甚至学了很久的人都可能没有搞明白。 为什么包含即可用?...所以实际上,你只是在你的.c中声明了这些函数,既然声明了,那么你就可以使用。但是你要想真正用到它,还需要找到它的定义。这是在链接阶段做的事情。...(-lm表示需要链接math库) 当然了,对于C++,使用pow函数不用链接math库也是可以的,为什么呢?请移步这里《C++为什么不需要单独链接math库?》。 不包含可以用吗?...那么一定要包含才可以使用吗?并非如此。前面说过了,包含不过是使用里面的声明,既然如何,我们自己声明怎么样?....); int main(void) { printf("hello,编程珠玑\n"); return 0 ; } 同样可以好好运行,因为你可以自己声明或者指定为外部声明。
看以下代码以及执行结果: public static void main(String[] args) { Integer a = 2; Integer b =...结果在判断c是否与d相等时 出现了false。 这是因为Integer类源码中有一个IntegerCache,这一个私有的内部类。这个类缓存了-128到 127之间数字的包装类。...需要记住它把一些数字的包装类提前缓存了,如果判断成立就把缓存中的那个包装类返回,如果不则new一个新的。 ? 可以看到判断缓存中是否存在,不存在new一个返回。...而我们 上边进行 = 和 == 的过程其实就是 java编译器把原始类行自动转换为封装类型的过程称之为**自动装箱**,相当于调用了上边所说的valueOf()方法。...所以如果进行比较的话最好使用equals方法来比较 在阿里开发手册中也有说到: ?
中的所有变长参数类型进行识别, * 对于memory_cl类型的参数,根据需要在kernel执行前上传数据到设备, * 并在kernel执行后根据需要下载输出数据到主机 * 模板中的N参数,用于调试时知道哪个参数出错...>::type k(kernel); 这里make_make_kernel也是一个模板函数,用来实例化cl::make_kernel类,为什么要这么做呢?...make_make_kernel模板函数就是实现这个功能的,下面是make_make_kernel的代码实现 /* 模板函数返回make_kernel执行里需要的类 * 对于普通的类,就是类本身 *...* 根据模板参数,创建cl::make_kernel类 * 创建cl::make_kernel类时所有的模板参数都会调用 kernel_type模板函数, * 以获取实例化cl::make_kernel...神奇的memory_cl 前面一直不断被提起的用来封装OpenCL内存对象的memory_cl是个什么神奇的东东?呵呵,其实并不复杂,就是抽象的基类而已,下面是这个类的主要实现代码和函数声明。
.直到 c++17,使用类模板都需要显式指定模板参数。...2.类模板的成员函数只有在调用的时候才会实例化。 2.3 部分使用类模板 1.类模板实例化时,模板实参只需要支持被实例化部分所有用到的操作。...1.可以对类模板的一个参数进行特化,类模板特化的同时需要特化所有的成员函数,非特化的函数在特化后的模板中属于未定义函数,无法使用。...7.6 关于模板参数声明的推荐方法 1.一般通常按值传递,如有特殊需要,可以结合实际按引用传递。 2.定义的函数模板要明确使用范围,不要过分泛化。...12.5 友元 将类模板作为友元时,必须保证友元定义位置已经知道类模板的声明。
,而且std::forward完全可以使用static_cast来代替 但是使用std::forward来代替std::move时,需要额外接收一个模板类型参数,且该模板参数不能是引用类型,因为编码方式决定了传递的值必须是一个右值...使用static_cast来代替std::forward时需要在每个需要的地方手动编写转换过程,这种方式不够简洁且会出错。...这样它就会产生许许多多的参数类型的重载实例函数。 在编译器为类自动生成移动和拷贝构造函数时,也不能使用重载过的通用引用参数构造函数,因为通用引用参数的构造函数在匹配顺序上会在其他重载函数之前。...另一种高级做法,限制(constraining)采用通用应用的模板 为了在特定的条件下,让函数调用发生在应该发生的位置上,我们需要根据条件来启用/禁用模板匹配,方式是std::enable_if,如果内部判断条件为...同样,在将MinVals传递到模板函数fwd中时,这个模板参数是一个引用,它本质上和指针是一样,只不过是一个会自动解引用的指针,那么在编译该函数时就需要对MinVals进行取地址,而MinVals此时并没有定义
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头文件中的一个类,关于enable_if的用法详细说明参见: class template std::enable_if...,但是却与C++14版本的make_unique在模板参数类型上并不兼容,你为啥知道C++14的make_unique版本是什么样呢?...+14的兼容性,应该使用这个版本。
介绍c++的SFINAE概念:类成员的编译时内省 0.导语1.C++自省?...int main() { f(1); } 经过上述的探讨,我们可以得到: 可惜has_type_x不是编译时,因此我们需要一个在编译时可确定的bool,引出sizeof运算符。...您可能还想知道为什么它不能与继承一起使用。C ++中的继承和动态多态性是一个在运行时可用的概念,换句话说,就是编译器将不会拥有且无法猜测的数据!...我带给您难题的最后一部分,称为enable_if。 如您所见,我们可以使用enable if根据编译时表达式触发替换失败。...序列化不需要任何更改,减去了STL中现在提供了enable_if函数的事实。
磁盘上叫page,缓存池中叫frame 使用ExtendebleHashTable将page_id映射到frame_id 使用LRUKReplacer类跟踪页面对象何时被访问,以便在必须释放一个帧以腾出空间从磁盘复制新的物理页面时...& constexpr if enable_if 以下内容来源于ChatGPT C++的enable_if是一个模板元编程工具,用于在编译时根据条件来选择是否启用或禁用特定的函数模板。...它可以与函数模板、类模板和模板别名一起使用。 enable_if通过在函数模板的返回类型中使用模板参数作为条件来工作。...当条件为true时,返回类型有效并启用函数模板; 当条件为false时,enable_if会导致编译器选择其他重载或者删除该函数模板。...使用场景: constexpr if 适用于需要在编译时进行条件分支的情况,例如根据类型或常量表达式的值执行不同的代码路径。
1 基本的type_traits C++ 11之前通过const或者enum枚举定义一个编译期常量的类型,在C++11中,则不需要这么定义,只需要从std::integral_constant进行派生即可...使用方法也很简单,派生integral_constant类后,则不用再新增定义类型和枚举变量。...std::result_of可以在编译器获取可调对象的返回类型,帮助解决编码过程中如下问题: 函数入参为模板参数,不能直接确定函数返回类型; 通过decltype推导函数返回类型时可读性差问题; 使用后置推导类型时...int main() { Fun(1); return 0; } 程序运行为最终会匹配到第二个模板函数,但是在实际的匹配过程中,当匹配到void Fun(T*)时用整数对T*进行替换是错误的...因此,它可以在编译期间检查模板参数是否有效。使用std::enable_if可以实现一个强大的重载机制,充分利用可以减少或者消除圈的复杂度。如:根据不同的数据基本类型转换为string进行输出。
我们知道,C++ 的模板有个规则是 SFINAE,这不是一个单词,而是 Substitution Failure Is Not An Error 的缩写,也就是说,编译器在基于模板生成代码时,如果将模板的类型参数置换为给定的类型时...>::type; 这里使用 void_t 将多个类型声明忽略掉以适应 template 中的第二个类型参数: decltype(std::begin...void_t,总体思路是类似的,也是基于类型声明来让编译器选择我们想要的模板实现,这里可能和上一个例子不太一样的有两点。...> 里有很多 is_ 开头的模板就是基于这两个类的,如果一个类型符合它的约束,它就是 true_type 否则就是 false_type。...——奇异递归模板模式,这个模式里派生类被作为基类的模板参数,这个声明看着有点吓人,但是它实现的效果是很妙的: using Number = StrongAlias<uint8_t, struct NumberTag
new ( size_t t){} // 注意函数的第一个参数和返回值都是固定的 void operator delete ( void * ptr){} // 重载了...new就需要重载delete 参考:https://www.cnblogs.com/vincently/p/4838283.html 宏定义特殊符号 定义在宏中才能编译通过 #字符串转换,如转换类名...#classname #@字符转换,输入超过4个字符报错,可以使用转换acsii ##合成新的符号,如class##A 模板类型限定 函数模板 template typename...std::enable_if ::value || std::is_same::value, void >::type...DataType including int and float"); 模板嵌套使用
当有项目中有多个地方需要在主机端进行向量数据的运算时,就会比较痛苦。...如果能像模板内核代码一样,为向量运算符提供简单的向量运算功能,就可以大大简化这些代码。 利用C++的模板计算函数,可以实现上面的功能。...(实现其他的运算符和函数也是差不多的代码,因为我暂时不需要就没有继续写下去)。...代码开始有两个很长的模板函数cl_vector_type和is_cl_vector,所有的其他函数模板都要用到这两个模板函数: cl_vector_type用于构造一个指定元素类型和长度的opencl...有了这些模板函数的支持,主机端opencl向量的运算就变得像在内核代码中一样简单,还以前面的例子用模板函数重写,就是这样: cl_int4 p1={4,2,0,9}; cl_int4 p2={3,9,-
于是我想到了我之前写的RAII类(参见我之前的博客《C++11实现模板化(通用化)RAII机制》),我的基本思路有了: 将每个java对象的local reference用我之前写的raii_var类封装成一个...改进raii_var 首先,为方便使用,我对《C++11实现模板化(通用化)RAII机制》中提到的raii_var类进行了改造,增加了*和->操作符: // *操作符,返回T对象引用 T...resource的地址 //这里->操作符使用了函数模板实现,用到了is_pointer和is_class两个type_trait来判断T的类型, //如果T不是指针,也不是class/struct,则没有..._get(),调用_get()时将raii_obj中的对象转成jstring类型 /* 根据 _T类型不同选择不同的函数模板 */ template<typename...,可以根据需要加入任意数目的参数 有了这个函数,就很方便的可以将任意一个函数(类成员函数/普通函数)的返回结果封装成一个raii_var对象。
从概念上理解的话,constexpr即常量表达式,重点在表达式字段,用于指定变量或函数可以在常量表达式中使用,可以(或者说一定)在编译时求值的表达式,而const则为了约束变量的访问控制,表示运行时不可以直接被修改...通过本示例,可以看出,将函数声明为constexpr可以提示效率,让编译器来决定是在编译阶段还是运行阶段来进行求值,当然了,如果想了解在编译阶段求值的各种细节规则,请参考constexpr in cppreference...if语句 如果您目前使用C++11进行编码,那么需要仔细阅读本节,这样可以为将来的版本升级打好基础;如果您正在使用C++17进行编码,那么更得阅读本节,相信读完本节后,会有一个不一样的认识。...在上述代码中,为了编译成功,我们引入了两个Square()模板函数借助std::enable_if来实现,代码上多少有点冗余,在这个时候,本节的主角if constexpr 出场,完整代码如下: #include...我们借助一个Square()函数模板以及更加符合编码习惯的if语句就能解决上面的问题,且比使用std::enable_if方式更为优雅和符合阅读习惯,进而提高代码的可阅读性。
C++ 中使用 std::shared_ptr 智能指针不当有可能会造成循环引用,因为 std::shared_ptr 内部是基于引用计数来实现的, 当引用计数为 0 时,就会释放内部持有的裸指针。...但是当 a 持有 b, b 也持有 a 时,相当于 a 和 b 的引用计数都至少为 1,因此得不到释放,RAII 此时也无能为力。这时就需要使用 weak_ptr 来打破循环引用。...这个就需要我们回过头来看 __enable_weak_this 的返回值类型,也就是下面这一坨: typename enable_if< is_convertible<_OrigPtr...这个就是模板元编程的特点,编译器生成模版函数和我们手写函数的逻辑完全不同,我们手写的函数不合法,编译器就会报错,但是如果编译器生成出来的发现不合法,编译器就会不生成这个函数。..._NOEXCEPT {} 对于第一个问题,就是 enable_if 起的作用: enable_if::type 的意思是说,如果bool值为true,enable_if 返回的就是第二个模版参数
版权声明:本文为博主原创文章,转载请注明源地址。...当调用该构造函数时,如果最后一个参数为右值引用的时候,会优先调用第一个构造函数,使用移动语义std:move()将rv转为右值,将rv的内容赋值给this->v,这时调用的是std::vector的移动赋值操作符...E为类模板参数,请忽视,下同。...std::move(v):v; }; 有了_ENABLE进行参数类型限制,在类中有多个类型的模板构造函数的情况,调用构造函数时就不会将别的类型的参数误传入,而产生编译错误。...这里用到的std::enable_if,std::is_base_of,std::decay都是定义在#include中的模板函数,详细说明请打开链接查看。
template 类模板,类模板成员实现在头文件中 template class MyPair{ T value[2]; }; 函数模板 template <typename...a : b; } 模板特例化 模板特例化和模板重载函数可以共存,编译期针对不同的数据类型,生成多个版本的函数,c++11之后可以使用constexpr常量表达式,写编译期代码 template class...template class Thing> class Crab{} Crab a;//使用模板作为类模板 函数模板参数 template...内部的类型 std::is_same_v 变量 std::remove_reference::type 变量 std::enable_if::type 条件满足返回类型...模板执行在编译器,所以模板成员只要传入的参数匹配,写固定的成员变量,只要编译过了也是可以的
特化 特化即是为以有的模板参数进行特殊化指定, 根据特化的范围和对象, 可以分为全特化/偏特化, 类特化/函数特化. 全特化 对一个特定参数集合自定义当前模板, 类模板和函数模板都可以全特化....全特化的模板参数列表应当为空, 并在模板实参中一一指定....foo() {}; template void foo() {}; 偏特化 偏特化是给自定义一个参数集合的模板, 偏特化后的模板需要进一步的实例化才能形成确定的签名....函数模板是不能进行偏特化的, 可以通过重载来代替偏特化的需要....< std::endl; } }; template class Foo<T, typename std::enable_if<std::is_base_of<Base
领取专属 10元无门槛券
手把手带您无忧上云