template模板三
来源:互联网 发布:人工智能基金如何买 编辑:程序博客网 时间:2024/05/14 14:04
三、模板的形参
有三种类型的模板形参:类型形参,非类型形参和模板形参。
1、类型形参
1.1 、类型模板形参:类型形参由关见字class或typename后接说明符构成,如template<class T> void h(T a){};其中T就是一个类型形参,类型形参的名字由用户自已确定。模板形参表示的是一个未知的类型。模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型说明符或类类型说明符的使用方式完全相同,即可以用于指定返回类型,变量声明等。
作者原版:1.2、 不能为同一个模板类型形参指定两种不同的类型,比如template<class T>void h(T a, T b){},语句调用h(2, 3.2)将出错,因为该语句给同一模板形参T指定了两种类型,第一个实参2把模板形参T指定为int,而第二个实参3.2把模板形参指定为double,两种类型的形参不一致,会出错。(针对函数模板)
作者原版:1.2针对函数模板是正确的,但是忽略了类模板。下面将对类模板的情况进行补充。
本人添加1.2补充版(针对于类模板)、当我们声明类对象为:A<int> a,比如template<class T>T g(T a, T b){},语句调用a.g(2, 3.2)在编译时不会出错,但会有警告,因为在声明类对象的时候已经将T转换为int类型,而第二个实参3.2把模板形参指定为double,在运行时,会对3.2进行强制类型转换为3。当我们声明类的对象为:A<double> a,此时就不会有上述的警告,因为从int到double是自动类型转换。
2、非类型形参
2.1 、非类型模板形参:模板的非类型形参也就是内置类型形参,如template<class T, int a> class B{};其中int a就是非类型的模板形参。
2.2、 非类型形参在模板定义的内部是常量值,也就是说非类型形参在模板的内部是常量。
2.3、 非类型模板的形参只能是整型,指针和引用,像double,String, String **这样的类型是不允许的。但是double &,double *,对象的引用或指针是正确的。
2.4、 调用非类型模板形参的实参必须是一个常量表达式,即他必须能在编译时计算出结果。
2.5 、注意:任何局部对象,局部变量,局部对象的地址,局部变量的地址都不是一个常量表达式,都不能用作非类型模板形参的实参。全局指针类型,全局变量,全局对象也不是一个常量表达式,不能用作非类型模板形参的实参。
2.6、 全局变量的地址或引用,全局对象的地址或引用const类型变量是常量表达式,可以用作非类型模板形参的实参。
2.7 、sizeof表达式的结果是一个常量表达式,也能用作非类型模板形参的实参。
2.8 、当模板的形参是整型时调用该模板时的实参必须是整型的,且在编译期间是常量,比如template <class T, int a> class A{};如果有int b,这时A<int, b> m;将出错,因为b不是常量,如果const int b,这时A<int, b> m;就是正确的,因为这时b是常量。
2.9 、非类型形参一般不应用于函数模板中,比如有函数模板template<class T, int a> void h(T b){},若使用h(2)调用会出现无法为非类型形参a推演出参数的错误,对这种模板函数可以用显示模板实参来解决,如用h<int, 3>(2)这样就把非类型形参a设置为整数3。显示模板实参在后面介绍。
2.10、 非类型模板形参的形参和实参间所允许的转换
1、允许从数组到指针,从函数到指针的转换。如:template <int *a> class A{}; int b[1]; A<b> m;即数组到指针的转换
2、const修饰符的转换。如:template<const int *a> class A{}; int b; A<&b> m; 即从int *到const int *的转换。
3、提升转换。如:template<int a> class A{}; const short b=2; A<b> m; 即从short到int 的提升转换
4、整值转换。如:template<unsigned int a> class A{}; A<3> m; 即从int 到unsigned int的转换。
5、常规转换。
/* ///////////////////////////////////////////////////////////////////// *//*! @file tripletpl.hxx @author night wing @date 2017/03 @brief The file declare the TripleTpl Template @par History @verbatim <author> <time> <version> <desc> chen 2016/11 0.1.0 build this module chen 2017/01 0.2.0 add. func chen 2017/03 0.3.0 add. TripleTpl( ) constructor with paramters chen 2017/03 0.4.0 add. lastReadable( ) API @endverbatim*//* ///////////////////////////////////////////////////////////////////// */#ifndef __SCIPACK_TRIPLETPL_HXX#define __SCIPACK_TRIPLETPL_HXX/*! @addtogroup SciPack @{*//*! @addtogroup devel @{*//*! @addtogroup devel_Exported_Classes @{*//* ///////////////////////////////////////////////////////////////////// config ///////////////////////////////////////////////////////////////////// */#if !defined( SCIPACK_HIDDEN )#if defined( _WIN32 ) || defined( __CYGWIN__ ) #define SCIPACK_HIDDEN#else #if __GNUC__ >= 4 #define SCIPACK_HIDDEN __attribute__ ((visibility ("hidden"))) #else #define SCIPACK_HIDDEN #endif#endif#endif#ifndef SCIPACK_NAMESPACE_BEGIN#define SCIPACK_NAMESPACE_BEGIN namespace SciPack {#define SCIPACK_NAMESPACE_END }#endif#ifndef SCIPACK_CLASS#define SCIPACK_CLASS( c ) SciPack::##c#endif#ifndef SCIPACK_CLASS_PTR#define SCIPACK_CLASS_PTR( c, obj ) (( SciPack::##c *)( obj ))#endif// /////////////////////////////////////////////////////////////////////// definition & include// ///////////////////////////////////////////////////////////////////// #include <stdint.h>#include <atomic> // C++11SCIPACK_NAMESPACE_BEGIN// ///////////////////////////////////////////////////////////////////////! Triple Template ( three object swap between two threads ) /*! this class is used for define the template of the user structure \n*/// ///////////////////////////////////////////////////////////////////// template <typename T > class TripleTpl {public: // ====================================================== // CTOR // ====================================================== TripleTpl ( ); TripleTpl ( T member_a, T member_b, T member_c ); virtual ~TripleTpl( ); // ====================================================== // Functions // ====================================================== T * writable( ); void swap( bool is_data_on = true, bool *is_old_data_picked = 0 ); const T * readable ( ); const T * lastReadable( ) { return & m_data[ m_out_idx ]; } bool isDataOn( ); void writeValue( const T &v ); T & readValue ( ); private: // ==================================================== // local var. // ==================================================== int m_in_idx, m_out_idx; std::atomic<int> m_tmp_idx; T m_data[3]; private: TripleTpl ( const TripleTpl & ); TripleTpl & operator=( const TripleTpl & ); // disable copy and assign};// ///////////////////////////////////////////////////////////////////// the template implement functions// ///////////////////////////////////////////////////////////////////template <typename T > TripleTpl<T> :: TripleTpl ( ) { m_in_idx = 0; m_out_idx = 2; m_tmp_idx.store(1); }template <typename T > TripleTpl<T> :: TripleTpl ( T member_a, T member_b, T member_c ) { m_in_idx = 0; m_out_idx = 2; m_tmp_idx.store(1); m_data[0] = member_a; m_data[1] = member_b; m_data[2] = member_c;}template <typename T > TripleTpl<T> :: ~TripleTpl ( ) { }template <typename T >T * TripleTpl<T> :: writable ( ) { return &m_data[ m_in_idx ]; }template <typename T >void TripleTpl<T> :: swap ( bool is_data_on, bool *is_old_data_picked ){ int tmp_idx; int flag = ( is_data_on ? 0x80 : 0x00 ); do { tmp_idx = m_tmp_idx.load( ); if ( m_tmp_idx.compare_exchange_strong( tmp_idx, m_in_idx | flag )) { m_in_idx = tmp_idx & 0x7f; break; } } while ( true ); if ( is_old_data_picked != 0 ) { *is_old_data_picked = ( tmp_idx & 0x80 ? false : true ); } }template <typename T >bool TripleTpl<T> :: isDataOn ( ) { int tmp_idx = m_tmp_idx.load( ); return ( tmp_idx & 0x80 ? true : false ); }template <typename T >const T* TripleTpl<T> :: readable ( ){ int tmp_idx; do { tmp_idx = m_tmp_idx.load( ); if ( m_tmp_idx.compare_exchange_strong( tmp_idx, m_out_idx )) { m_out_idx = ( tmp_idx & 0x7f ); if ( m_out_idx > 2 ) { m_out_idx = 0; } break; } } while ( true ); return ( tmp_idx & 0x80 ? & m_data[ m_out_idx ] : nullptr );}template <typename T >void TripleTpl<T> :: writeValue( const T &v ){ T *w = this->writable( ); *w = v; this->swap( true, NULL );}template <typename T >T & TripleTpl<T> :: readValue ( ) { if ( this->isDataOn( )) { this->readable( ); } // update if necessary. return m_data[ m_out_idx ];}SCIPACK_NAMESPACE_END/*! @}*//*! @}*//*! @}*/#endif
- template模板三
- C++ 模板类(廿三)--template模板类使用
- 模板Template
- 模板Template
- 模板(template)
- template 模板
- 模板template
- 模板(Template)
- template模板
- template模板
- template模板
- 模板template
- 模板template
- 模板template
- C++设计模式<三>:模板方法(Template Method 模式)
- vue的模板 <template></template>
- 设计模式学习笔记(三):模板方法模式【Template Method】(三) 问题引申
- C++ template 模板 模板别名
- C++ Primer Plus第四章课后编程答案
- centos7系统下nginx安装并配置开机自启动操作
- 深夜幻想
- 技术文章 | 深度学习在推荐领域的应用:Lookalike 算法
- HttpClient中post请求http、https示例
- template模板三
- Intellij IDEA 快捷键
- 简单方便的api接口测试工具:Chrome浏览器插件postman
- WebService到底是什么?
- 2.20178-28
- wait(),notify(),notifyAll()及sleep() 和wait()的区别
- 写一个基于Servlet的接口测试工具
- Kubernentes中的身份验证
- STM8学习笔记---串口uart1