精华内容
下载资源
问答
  • 包含内容:traits-6.1.0-cp36-cp36m-win_amd64.whl 安装tvtk需要 VTK-7.1.1-cp36-cp36m-win_amd64.whl numpy-1.12.1+mkl-cp36-cp36m-win_amd64.whl traits-4.6.0-cp36-cp36m-win_amd64.whl mayavi-4.5.0+vtk71-cp36...
  • callable_traits, callable类型的现代 C 型特征和泛函 Boost.CallableTraits CallableTraits是一个C 11头库,用于检查。合成和分解可以调用类型。这里有最新的文档,这里是 。在CallableTraits中,被正式地检查过,...
  • 利用Python做可视动画,在安装traits的时候一定要对应版本,否则很容易报错。这个traits5.2.0是可以用的,之后我会上传其他的对应的几个板块。
  • Traits 项目是所有 Enthought 工具套件开发的中心,它改变了 Enthought 使用已经非常高效的 Python 编程语言进行编程的思维模型。 我们鼓励每个人与我们一起享受使用如此强大的方法所带来的生产力收益。 Traits ...
  • 在 PHP 5.4 中 一个新的语言特性被添加进来,这就是众所周知的 Traits,它在 Laravel 框架中被广泛使用。 PHP 官方网站给出了 Traits 的定义,如下: “ Trait 是单继承语言(如 PHP )中的一种代码复用机制。 Trai ...
  • 本文实例讲述了thinkPHP5.0框架引入Traits功能。分享给大家供大家参考,具体如下: ThinkPHP 5.0开始采用trait功能(PHP5.4+)来作为一种扩展机制,可以方便的实现一个类库的多继承问题。 Traits 是一种为类似 PHP ...
  • 支持python3.7版本,支持python3.7版本,支持python3.7版本
  • Python科学计算三维可视化应用中需要安装TVTK库,traits-4.6.0-cp36-cp36m-win_amd64.whl为安装TVTK库所需要的5个库之一,该库为64位的
  • traits

    2021-04-28 16:50:03
    traits 扮演的是“特性萃取机”的角色 迭代器所指向的对象的型别称为该迭代器的value type,虽然可以通过template来推导参数型别,但是若value type要用于函数的返回值,就没有办法了 用于获取各个迭代器的特性比如...

    traits 扮演的是“特性萃取机”的角色

    迭代器所指向的对象的型别称为该迭代器的value type,虽然可以通过template来推导参数型别,但是若value type要用于函数的返回值,就没有办法了

    用于获取各个迭代器的特性比如迭代器的value_type,difference_type等,因此迭代器应该提供标准接口,体现在iterator.h处,将在迭代器笔记处补全含义
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    特偏化partial specialization

    含义:提供另一份template定义式,本身仍为templatized,即针对参数更进一步的条件限制设计的特化版本

    //允许接受任何型别
    template<typename T>
    class C{...}
    //接受T为原生指针
    template<typename T>
    class C<T*>{...}
    
    //利用上述特性得到value type
    //含义为,如果T有定义自己的value type,那么通过traits得到value type。
    template<class T>
    struct iterator_traits{
        using value_type = typename T::value_type;
    };
    
    //迭代器是个原生指针
    template<class T>
    struct iterator_traits<T*>{
        using value_type = T;
    };
    

    __type_trait__type_traits

    __iterator_trait负责萃取迭代器的特性,__type_trait负责萃取型别type的特性。
    比如:是否具备non-trivial defalt ctor?non-trivial copy ctor…?
    如果否定,则在进行某些操作,如构造,析构,拷贝等可以直接采用内存操作,如malloc,memcpy,而不用调用constructor,destructor等,可以提高效率(在第二章中的内存分配有所体现)
    在这里插入图片描述
    在这里插入图片描述

    integral_constant

    integral_constant 是模板元编程的一个重要的类, 它的作用是定义类型的常量.
    它定义了 bool_constant, true_type 和 false_type.
    实现代码:

    展开全文
  • traits-6.2.0-cp310-cp310-win32
  • traits-6.2.0-pp37-pypy37_pp73-win_amd64
  • traits-4.6.0-cp34-cp34m-win32
  • 设计一个Measurement计量单位类型,满足如下要求, 1.当为距离单位,当构造米或者千米等不同距离单位的实例时,统一以米为基本单位,实例调用description函数返回单位...注意:代码实现中运用了模板中的traits技术。
  • num-traits:Rust中通用数学的数字特征
  • traits python win32

    2018-06-13 13:29:57
    PyQt4-->traits-->VTK7.1-->mayavi-4.5.0,安装mayavi血泪史,一定要这个,缺一不可
  • type_traits

    千次阅读 2019-07-29 18:31:00
    type_traits提供了丰富的编译期间计算、查询、判断、转换和选择的帮助类,其被定义在#include <type_traits>下。 作用: 增强了泛型编程能力; 增强程序的弹性,使得在编译期间就可以做到优化、改进甚至...

     

    概述

    type_traits提供了丰富的编译期间计算、查询、判断、转换和选择的帮助类,其被定义在#include <type_traits>下。

    作用:

    • 增强了泛型编程能力;
    • 增强程序的弹性,使得在编译期间就可以做到优化、改进甚至排错,提高代码质量;
    • 它所提供的选择功能一定程度上可以消除冗长的if-else或switch-case语句,降低程序的圈复杂度,提高代码的可维护性;
    • 它所提供的判断功能,在编译期间可以检查出是否是正确的类型,以便能编写更为安全的代码。

     

    • Helper Class

    作用: 帮助创建编译时常量的标准类。

    在C++11之前我们定义编译期常量的方法:

    1.  通过定义静态变量,并通过CompileTimeContents::value方式获取该常量。

        template<typename Type>
        struct CompileTimeContents{
            static const int value = 1;
        };

    2.  通过定义枚举变量方式。

        template<typename Type>
        struct CompileTimeContents{
           enum {value = 1};
        };

    但在C++11中可以通过std::integral_constant 模版类派生:

        template<typename Type>
        struct CompileTimeContents :std::integral_constant<int, 1>
        {
        };

    通过CompileTimeContents<type_name>::value方式获取该常量,这种写法好处是不用再定义额外变量,使用起来更加方便。

    在标准库中的定义:

        template <class T, T v>
        struct integral_constant {
          static constexpr T value = v;
          typedef T value_type;
          typedef integral_constant<T,v> type;
          constexpr operator T() { return v; }
        };

     

    • 判断类型

    在traits中判断类型的模板类 都 继承自 std::integral_constant

    1.  判断目标类型是否为期望类型。

    traits判断类型(下表展示部分,其他可到 http://www.cplusplus.com/reference/type_traits/ 查看):

    traits类型说明

    is_array

    判断是否为数组类型

    is_class

    判断是否为类类型而不是union类型

    is_function

    判断是否为函数类型

    is_reference

    判断是否为引用类型

    is_pod

    判断是否为POD(传统Cstruct类型)

    is_trivial

    判断是否为内置类型

    使用实例:

    // is_array example
    #include <iostream>
    #include <array>
    #include <string>
    #include <type_traits>
    
    int main() {
      std::cout << std::boolalpha;
      std::cout << "is_array:" << std::endl;
      std::cout << "int: " << std::is_array<int>::value << std::endl;
      std::cout << "int[3]: " << std::is_array<int[3]>::value << std::endl;
      std::cout << "array<int,3>: " << std::is_array<std::array<int,3>>::value << std::endl;
      std::cout << "string: " << std::is_array<std::string>::value << std::endl;
      std::cout << "string[3]: " << std::is_array<std::string[3]>::value << std::endl;
      return 0;
    }

    运行结果:

    判断类型通常会与std::enable_if结合使用,通过SFINAE(替换非错误)特性来实现功能更强的重载。

     

    2.  判断两个模板类型之间的关系。

    traits类型说明
    is_same判断两个类是否相同
    is_base_of判断Base类型是否为Derivedl 类型的基类
    is_convertible判断前面模板参数类型能否转换为后面模板参数类型

     具体用法在官网依然有示例:

    // is_base_of example
    #include <iostream>
    #include <type_traits>
    
    struct A {};
    struct B : A {};
    
    int main() {
      std::cout << std::boolalpha;
      std::cout << "is_base_of:" << std::endl;
      std::cout << "int, int: " << std::is_base_of<int,int>::value << std::endl;
      std::cout << "A, A: " << std::is_base_of<A,A>::value << std::endl;
      std::cout << "A, B: " << std::is_base_of<A,B>::value << std::endl;
      std::cout << "A, const B: " << std::is_base_of<A,const B>::value << std::endl;
      std::cout << "A&, B&: " << std::is_base_of<A&,B&>::value << std::endl;
      std::cout << "B, A: " << std::is_base_of<B,A>::value << std::endl;
      return 0;
    }

    运行结果:

     

    • 类型转换

    traits中给出了对参数属性的修改接口,如:其cv属性额添加或移除、引用的添加或移除、数组维度的修改等。

    traits类型说明
    remove_cv移除cv属性
    add_cv添加cv属性
    remove_reference移除引用
    add_lvaue_reference添加左值引用
    remove_extent移除数组顶层维度

    示例:

    // remove_cv example
    #include <iostream>
    #include <type_traits>
    
    int main() {
      typedef const volatile char cvchar;
      std::remove_cv<cvchar>::type a;       // char a
      std::remove_cv<char* const>::type b;  // char* b
      std::remove_cv<const char*>::type c;  // const char* c (no changes)
    
      if (std::is_const<decltype(a)>::value)
        std::cout << "type of a is const" << std::endl;
      else
        std::cout << "type of a is not const" << std::endl;
    
      if (std::is_volatile<decltype(a)>::value)
        std::cout << "type of a is volatile" << std::endl;
      else
        std::cout << "type of a is not volatile" << std::endl;
    
      return 0;
    }

    运行结果:

     

    • 根据条件选择traits

    std::conditional 在编译期间根据判断式选择两个类型中的一个,类似于常用的条件表达式。

    template <bool Cond, class T, class F> struct conditional;

              当条件为真返回T类型,条件为假返回F类型。

    例如:比较long long类型与long double 返回较大的类型

    #include <iostream>
    #include <typeinfo>
    #include <type_traits>
    
    int main() {
    	typedef std::conditional<(sizeof(long long) > sizeof(long double)), \
    		long long, long double > ::type max_size_t;
    	std::cout << typeid(max_size_t).name() << std::endl;
    
    	return 0;
    }

    运行结果:

     

    • 可调用对象返回值类型

    通常我们获取函数返回值的类型使用的是decltype方式:

    template<typename T, typename Arg>
    auto Func(T a, Arg arg)->decltype(f(arg))
    {
        return f(arg);
    }

    但是在某个类型没有模板参数时,就不能通过decltype来获取类型

    #include <iostream>
    #include <type_traits>
    
    class A{
    	A() = delete;
    
    public:
    	int operator()(int i){
    		return i;
    	}
    };
    
    int main() {
    	// decltype(A()(0)) i = 4;
    	decltype(std::declval<A>()(std::declval<int>())) i = 4;
    	
    	std::cout << typeid(decltype(std::declval<A>()(std::declval<int>()))).name() << std::endl;
    	std::cout << i << std::endl;
    
    	return 0;
    }

    当用仅用decltype方式获取类型时,由于A没有默认构造函数,代码出错。

    之后采用declval方式,通过 declval<A>() 获取任意类型的临时值,但临时值不能用于求值,需要借助decltype对临时值进行类型推导,得出最终返回值。

    在traits中提供了另一解决途径:std::result_of

    	std::result_of<A(int)>::type i = 4;
    

    函数原型: 

        // 第一个模板参数为可调用对象类型,第二个模板参数为参数类型
        template <class Fn, class... ArgTypes> 
        struct result_of<Fn(ArgTypes...)>;

     

    • ​​​​​​​根据条件禁用或启用某些类型

    编译器在匹配重载函数时,通常匹配所有的重载函数,匹配一个如果失败了,编译器不会报错,而是接着匹配其他重载函数,选择最精确的一个去执行,整个过程不会报错(SFINAE)。

    tratis中std::enable_if 根据限定条件选择重载函数,只对满足条件的函数有效。可作用于返回值、模板定义、类模板特化、参数类型限定。

    函数原型:

        template <bool Cond, class T = void> 
        struct enable_if;

    用法示例:

    #include <iostream>
    #include <type_traits>
    
    // 1. 对函数返回值限定,只有模板参数T是integral类型时,才执行此函数
    template <class T>
    typename std::enable_if<std::is_integral<T>::value, bool>::type
    is_odd(T i) { return bool(i % 2); }
    
    
    // 2. 对模板参数限定,模板特化时,模板参数只能是intergal类型
    template < class T,
    class = typename std::enable_if<std::is_integral<T>::value>::type>
    	bool is_even(T i) { return !bool(i % 2); }
    
    
    int main() {
    
    	short int i = 1;    // code does not compile if type of i is not integral
    
    	std::cout << std::boolalpha;
    	std::cout << "i is odd: " << is_odd(i) << std::endl;
    	std::cout << "i is even: " << is_even(i) << std::endl;
    
    	return 0;
    }

    且通过编译期检查输入模板参数是否有效,来提前显示编译错误,避免运行时才被发现。

    ​​​​​​​

    展开全文
  • laravel-controller-repository-traits:Laravel便利的控制器特质,使用prettusl5-repository
  • 笔记-traits技巧讲解

    2020-10-01 20:25:59
    侯捷老师在《STL源码剖析》中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘。如此一说,其重要性就不言而喻了。 之前已经介绍过迭代器,知道了不同的数据结构都有自己专属...

         侯捷老师在《STL源码剖析》中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘。如此一说,其重要性就不言而喻了。
           之前已经介绍过迭代器,知道了不同的数据结构都有自己专属的迭代器,不同的迭代器也有不同的特性,由于算法的接口是统一的,通过迭代器的不同属性,算法自动选择正确的执行流程,在完全任务的同时,也尽可能提高算法的执行效率。那算法如何获知迭代器的属性呢?这一光荣的任务就是traits完成的。在STL实现中,traits编程技术得到大量的运用,它利用了“内嵌类型”的编程技巧与C++的template参数推导功能,弥补了C++类型识别方面的不足。通过traits,算法可以原汁原味的将迭代器的属性萃取出来,帮助算法正确高效的运行。

    一、为什么需要traits编程技术

         前面说了很多关于traits的光荣事迹,但是却一直没有介绍traits究竟是个什么东西,究竟是用来干什么的?traits在英文解释中就是特性,下面将会引入traits技术的作用,一步一步地揭开其神秘的面纱。

    1.1 内嵌类型声明

    1.1.1 以迭代器所指对象的类型声明局部变量

           下面是一个以迭代器为模板形参的函数模板:

    template<typename Iterator>
    
    void func(Iterator iter){
           //函数体
    }

           假如现在算法中需要声明一个变量,而变量的类型是迭代器所指对象的类型,应该怎么处理呢?

    template<typename Iterator>
    
    void func(Iterator iter){
       *Iterator var;//这样定义变量可以吗?
    }

           上面的代码是不可以通过编译的,虽然C++支持sizeof(),但是并不支持typeof(),就算是用到RTTI性质中的typeid(),获取到的也仅仅是类型的名字,因此不能直接用来声明变量。此时可以利用函数模板的参数类型推导机制解决问题,例如:

    template<typename Iterator, typename T>
    
    void func_impl(Iterator iter, T t){
       T temp;//这里就解决了问题
       //这里做原本func()的工作
    }
    
    
    template<typename Iterator>
    
    void func(Iterator iter){
       func_impl(iter, *iter);//func的工作全部都移到func_impl里面了
    }
    
    
    int main(int argc, const char *argv[]){
       int i;
       func(&i);
    }

      函数func作为对外接口,实际的操作却由函数func_impl执行,通过函数func_impl的参数类型推导,获取到Iterator指向对象的类型T,从而解决了问题。

    1.1.2 以迭代器所指对象的类型声明返回类型

           现在通过函数模板的参数类型推导解决了函数体内声明变量的问题,但问题又来了,如果需要返回类型是迭代器所指对象的类型又可以怎样做呢?

    template<typename Iterator>
    
    (*Iterator) func(Iterator iter){
       //这样定义返回类型可以吗?
    }

           在这种情况下,模板的参数类型推导机制也无能为力了,因为它只能推导参数,并不能推导函数的返回类型。STL解决这种问题的办法就是内嵌类型声明,即在迭代器内部添加一种“特性”,通过这种“特性”,算法可以很容易地获知迭代器所指对象的类型,请看下面的代码:

    template<typename T>
    class Iterator{
    public:
       typedef T value_type;//内嵌类型声明
       Iterator(T *p = 0) : m_ptr(p) {}
       T& operator*() const { return *m_ptr;}
      //...
    private:
       T *m_ptr;
    };
    
    
    template<typename Iterator>
    typename Iterator::value_type //以迭代器所指对象的类型作为返回类型,长度有点吓人!!!
    func(Iterator iter){
      return *iter;
    }
    
    int main(int argc, const char *argv[]){
       Iterator<int> iter(new int(10));
       cout<<func(iter)<<endl; //输出:10
    }

           函数func()的返回类型前面必须加上关键词typename,原因在本人之前写的“C++模板学习”中也解释过,因为T是一个template参数,编译器在编译实例化func之前,对T一无所知,就是说,编译器并不知道Iterator<T>::value_type是一个类型,或者是一个静态成员函数,还是一个静态数据成员,关键词typename的作用在于告诉编译器这是一个类型,这样才能顺利通过编译。

     

    1.2 原生指针也是一种迭代器

           之前在介绍迭代器的分类之时说过,原生指针也是一种迭代器,此时问题就来了,原生指针并不是一种类类型,它是无法定义内嵌类型的。因此,上面的内嵌类型实现还不能完全解决问题,那可不可以针对原生指针做特殊化的处理呢?答案是肯定的,利用模板偏特化就可以做到了。

           《泛型思维》一书对模板偏特化的定义是:

            针对template参数更进一步的条件限制所设计出来的一个特化版本。

    //这个泛型版本允许T为任何类型
    
    template<typename T>
    
    class C{
    //...
    };

           我们很容易接受上面的类模板有一个形式如下的偏特化版本:

    template<typename T>
    
    class C<T*>
    
    {
    
    //...
    
    };

           这个特化版本仅适用于T为原生指针的情况,”T为原生指针”就是“T为任何类型”的一个更进一步的条件限制。那如何利用模板偏特化解决原生指针不能内嵌类型的问题呢?下面介绍的iterator_traits就是关键了。

     

    二、迭代器萃取机--iterator_traits

    2.1 原生指针并不是一种类类型

           STL里面使用iterator_traits这个结构来专门“萃取”迭代器的特性,前面代码中提到的value_type就是迭代器的特性之一:

    template<typename Iterator>
    
    struct iterator_traits{
       typedef typename Iterator::value_type value_type;
    };

           如果Iterator有定义value_type,那么通过iterator_traits作用之后,得到的value_type就是Iterator::value_type,比较之前写的版本和经iterator_traits作用后的版本:

    template<typename Iterator>
    typename Iterator::value_type //这行是返回类型
    func(Iterator iter){
      return *iter;
    }
    
    
    //通过iterator_traits作用后的版本
    template<typename Iterator>
    typename iterator_traits<Iterator>::value_type //这行是返回类型
    func(Iterator iter){
      return *iter;
    }

           从长度上看,好像需要敲的代码更多了,为什么要这么麻烦加上一层间接层呢?由于原生指针也是一种迭代器,而且不是一种类类型,因此原生指针并不能定义内嵌类型。这里通过实现iterator_traits的一个偏特化版本就可以解决这个问题了,具体的实现如下:

    //iterator_traits的偏特化版本,针对迭代器是个原生指针的情况
    
    template<typename T>
    
    struct iterator_traits<T*>{
      typedef T value_type;
    };

           大家在进行函数重载的时候,应该都曾遇到过以下的情况:

    //函数版本一
    
    void func(int *ptr){
      //...
    }
    
    
    //函数版本二
    void func(const int *ptr){
      //...
    }

           以上两个函数虽然函数、形参个数和位置都一样,但它们不是同一个函数,而是函数重载的一种情况,也就是说函数形参的const和非const版本是不一样的,在函数版本一里面,可以修改指针ptr指向的数据,但是在函数版本二里面却不可以,因为传入的指针ptr是一个const指针。由此可以联想到,当将一个const指针作为模板形参传给前面声明的偏特化版本的iterator_traits会有发生什么情况呢?

    iterator_traits<const int*>::value_type  //获得的value_type是const int,并不是int

           当我们想用iterator_traits萃取出value_type并声明一个临时变量时,却发现声明的变量是const类型,并不能进行赋值,这违背了我们的用意。我们需要一种方法区别const和非const才能避免这种误会的发生,答案很简单,只要另外再设计一个iterator_traits偏特化版本就可以了:

    template<typename T>
    
    struct iterator_traits<const T*>{
       typedef T value_type;
    }

           现在,不论是自定义的迭代器,还是原生指针int*或者是const int*,都可以通过iterator_traits获取到正确的value_type。

     

    2.2 iterator_traits中定义的类型

           STL根据经验,定义了迭代器最常用到的五种类型:value_type、difference_type、pointer、reference、iterator_category,任何开发者如果想将自己开发的容器与STL结合在一起,就一定要为自己开发的容器的迭代器定义这五种类型,这样都可以通过统一接口iterator_traits萃取出相应的类型,下面列出STL中iterator_traits的完整定义:

    tempalte<typename I>
    
    struct iterator_traits{
       typedef typename I::iterator_category iterator_category;
       typedef typename I::value_type value_type;
       typedef typeanme I:difference_type difference_type;
       typedef typename I::pointer pointer;
       typedef typename I::reference reference;
    };

           下面会分别介绍一下这五种类型:

    (1) 迭代器类型之一:value_type
           value_type就是指迭代器所指对象的类型,例如,原生指针也是一种迭代器,对于原生指针int*,int即为指针所指对象的类型,也就是所谓的value_type。

    (2) 迭代器类型之二:difference_type
           difference_type用来表示两个迭代器之间的距离,例如:

    int array[5] = {1, 2, 3, 4, 5};
    int *ptr1 = array + 1;//指向2
    int *ptr2 = array + 3;//指向4
    ptrdiff_t distance = ptr2 - ptr1;//结果即为difference_type

           上面代码中,指针ptr2与ptr1相减的结果的类型就是difference_type,对于原生指针,STL以C++内建的ptrdiff_t作为原生指针的difference_type。

    (3) 迭代器类型之三:reference_type

           reference_type是指迭代器所指对象的类型的引用,reference_type一般用在迭代器的*运算符重载上,如果value_type是T,那么对应的reference_type就是T&;如果value_type是const T,那么对应的reference_type就是const T&。

    (4) 迭代器类型之四:pointer

           pointer就是指迭代器所指的对象,也就是相应的指针,对于指针来说,最常用的功能就是operator*和operator->两个运算符。因此,迭代器需要对这两个运算符进行相应的重载工作:

    T& operator*() const { return *ptr; } // T& is reference type
    
    T* operator->() const { return ptr; } // T* is pointer type

    (5) 迭代器类型之五:iterator_category

           iterator_category的作用是标识迭代器的移动特性和可以对迭代器执行的操作,从iterator_category上,可将迭代器分为Input Iterator、Output Iterator、Forward Iterator、Bidirectional Iterator、Random Access Iterator五类,具体为什么要这样分类,简单来说,就是为了尽可能地提高效率,这也是STL的宗旨之一。具体的情况已经在本人的“《STL源码剖析》学习之迭代器”中详细介绍过,这里就不在多说了。

     

    2.3 iterator_traits完整定义

     

           为了保证iterator_traits可以正常工作,STL提供了一个iterator类,所有自定义的迭代器都必须继承自它,这样才能保证这些自定义的迭代器可以顺利地狱其它STL组件进行协作,iterator类具体定义如下:

    template<typename Category,
    typename T,
    typename Distance = ptrdiff_t,
    typename Pointer = T*,
    typename Reference = T&>
    
    struct iterator{
      typedef Category iterator_category;
      typedef T value_type;
      typedef Distance difference_type;
      typedef Pointer pointer;
      typedef Reference reference;
    };

           类iterator不包含任何成员变量,只有类型的定义,因此不会增加额外的负担。由于后面三个类型都有默认值,在继承它的时候,只需要提供前两个参数就可以了,如:

    template <typename T>
    class ListIter : public std::iterator<std::forward_iterator_tag, T>{
    //...
    }

     

     ************************************************************更新******************************************************************************

    在c++11中有了auto和decltype类型推导功能.,就不用用这么多间接层去实现其实很简单的需求了,直接像下面这样写就可以了.

    template<typename Iterator>
    auto func(Iterator iter)-> decltype(*iter){
      return *iter;
    }

     

    展开全文
  • traits-6.1.1-cp36-cp36m-win_amd64
  • Boost.CallableTraits CallableTraits是一个C ++ 11仅限标头的库,用于检查,合成和分解可调用类型。 最新文档可。 CallableTraits已被并被。 CallableTraits在Boost 1.66(2017年12月)及更高版本中可用。...
  • Laravel开发-laravel-model-traits 与Laravel 5模型一起使用的特性集合。
  • traits的作用和使用

    千次阅读 2020-01-02 09:58:53
    raits是在5.4中新增的一个用于实现代码重用的方法。 php是一种单一继承的语言,我们无法像java一样在一个class中extends多个基类来实现代码重用,现在Traits能解决这一代码重用的...Traits 和class相似,但是仅...

    raits是在5.4中新增的一个用于实现代码重用的方法。

     

    php是一种单一继承的语言,我们无法像java一样在一个class中extends多个基类来实现代码重用,现在Traits能解决这一代码重用的问题,它能让开发者在多个不同的class中实现代码重用。

    Traits和class在语义的定义上都是为了减少代码的复杂性,避免多重继承的问题。

     

    Traits 和class相似,但是仅用于以统一和较细粒度的方式来提供一组功能,在Traits内部无法进行实例化,即不存在类似class的构造函数__construct()。Traits作为一个php传统继承的扩展并实现水平集成;因此,在应用程序的class中可以不再需要继承。

     

    1)如何使用

    在类中用关键字'use' 来引用 Traits。多个Traits 用','隔开。

    实例代码如下:

    <?php
    trait ezcReflectionReturnInfo {
    function getReturnType() {
    }
    function getReturnDescription() {
    }
    }class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */
    }
    class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
    }
    ?>
    

     

    2)优先级
    基类中的成员函数将被Traits中的函数覆盖,当前类中的成员函数将覆盖Traits中的函数。

    <?php
    class Base {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait SayWorld {
        public function sayHello() {
            parent::sayHello();
            echo "World!\n";
        }
    }
    
    class MyHelloWorld extends Base {
        use SayWorld;
    }
    
    class MyHelloWorldExt extends Base {
        use SayWorld;
        public function sayHello() {
            /**
             * 这里是5.4中的新的改动,5.4之前的版本会提示:
             * PHP Fatal error:  Cannot use string offset as an array
             * 5.4中改进为返回字符串中的该索引号的字符
             */
            $str  = "Arvin";
            echo $str[0][0];// echo 'A';
        }
    
        public function shortArray() {
            $array = ['first', 2, 3, 4];//5.4中的数组简单语法
            echo $array[0];//5.4中的数组解引用取数组元素方法
        }
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $oe = new MyHelloWorldExt();
    $oe->sayHello();
    echo "\n";
    $oe->shortArray();
    

     

    输出:
    Hello World!
    A
    first
    

     

    3)多Traits

    多个Traits可以添加到一个class的声明中,多个Traits之间用","隔开。

    <?php
    trait Hello {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait World {
        public function sayWorld() {
            echo 'World';
        }
    }
    
    class MyHelloWorld {
        use Hello, World;
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    

     

    输出结果:

    Hello World

     

    4)多Traits冲突

    如果添加到同一个class的两个Traits中有相同的函数名称,且没有明确的进行处理,将产生一个错误。

    为了解决同一个类中两个Tratis中的同名函数冲突,需要用insteadof操作符来选择正确的函数。

    因为方法的唯一性和排他性,'as'操作符允许用在冲突函数之后以解决内部冲突的问题。

    <?php
    trait A {
    public function smallTalk() {
    echo 'a';
    }
    public function bigTalk() {
    echo 'A';
    }
    }
    
    trait B {
    public function smallTalk() {
    echo 'b';
    }
    public function bigTalk() {
    echo 'B';
    }
    }
    
    class Talker {
    use A, B {
    B::smallTalk insteadof A;
    A::bigTalk insteadof B;
    }
    }
    
    class Aliased_Talker {
    use A, B {
    B::smallTalk insteadof A;
    A::bigTalk insteadof B;
    B::bigTalk as talk;
    }
    }
    

     

    上面的例子中,Talker使用Traits A 和B,因此两者中相同的函数名称存在冲突。

    alker中定义了smallTalk取自Traits B,bigTalk取自Traits A。

    Aliased_Talker中通过使用as操作符来确保Traits B中的bigTalk通过别名talk来实现。

    5)改变函数访问权限

    我们可以使用as语法来改变Traits中函数的访问权限属性。

    <?php
    trait HelloWorld {
    public function sayHello() {
    echo 'Hello World!';
    }
    }
    
    // Change visibility of sayHello,改变sayHello的访问权限。
    class MyClass1 {
    use HelloWorld { sayHello as protected; }
    }
    
    // Alias method with changed visibility
    // sayHello visibility not changed,设置别名myPrivateHello。
    class MyClass2 {
    use HelloWorld { sayHello as private myPrivateHello; }
    }
    

     

    6)Traits组成新Traits
    就像许多类一样可以在类中使用Traits,Traits中一样可以使用Traits。可以在一个Traits中定义一个或者多个Traits,这些Traits 可以作为部分或者全部成员被定义在其他Traits中。

    <?php
    trait Hello {
    public function sayHello() {
    echo 'Hello ';
    }
    }
    
    trait World {
    public function sayWorld() {
    echo 'World!';
    }
    }
    
    trait HelloWorld {
    use Hello, World;
    }
    
    class MyHelloWorld {
    use HelloWorld;
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    

    以上例程会输出:Hello World!

     

    7)抽象Trait成员
    为了在类中强制实现某些方法,可以在Traits中使用抽象方法。
    例如:

    <?php
    trait Hello {
        public function sayHelloWorld() {
            echo 'Hello '.$this->getWorld();
        }
        abstract public function getWorld();
    }
    
    class MyHelloWorld {
        private $world;
        use Hello;
        public function __construct($world) {
            $this->world = $world;
        }
        public function getWorld() {
            return $this->world;
        }
    }
    
    /**
     * 这里用到了5.4新功能 类实例化解引用操作
     * (new class())->method();
     */
    (new MyHelloWorld('Arvin'))->sayHelloWorld();
    ?>
    
    该实例输出:
    Hello Arvin
    

     

    8)静态Trait成员

    在Traits中不能定义static 静态变量,但是可以定义在Tratis的函数中。Tratis中同样可以定义静态函数。

    <?php
    trait Counter {
        public function inc() {
            static $c = 0;//静态变量
            $c += 1;
            echo "$c\n";
        }
        /**
         * 静态方法
         */
        public static function doSomething() {
            echo 'Doing something';
        }
    }
    
    class C1 {
        use Counter;
    }
    
    (new C1())->inc(); // echo 1
    C1::doSomething();
    ?>
    输出为:
    1
    Doing something
    

     

    9) Traits 定义属性

    如果在一个trait中定义了一个属性,则在引用该trait的类中不能定义同名的属性,如果该类中定义有和trait中已定义属性具有相同的名字和访问可见性,则是一个E_STRICT 提示,否则抛出语法错误。

    <?php
    trait PropertiesTrait {
        public $x = 1;
        public $y = 2;
    }
    
    class PropertiesExample {
        use PropertiesTrait;
        public $x = 1;
        //public $y = 3;
    }
    
    $example = new PropertiesExample;
    echo $example->x, $example->y;
    ?>
    
    输出:
    12
    

     

     

    展开全文
  • 本篇文章基于gcc中标准库源码剖析一下标准库中的模板类pointer_traits,并且以此为例理解一下traits技法。 说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。 还是先看一下思维导图,如下: 1. ...
  • type_traits 类型萃取

    2020-02-15 14:57:47
    一、 c++ traits traits是c++模板编程中使用的一种技术,主要功能: 把功能相同而参数不同的函数抽象出来,通过traits将不同的参数的相同属性提取出来,在函数中利用这些用traits提取的属性,使得函数对不同的参数...
  • __alloc_traits特性 类__allocator_traits_base,用于获取内存分配器Alloc的属性,内存分配器不一定是std::allocator,可以是自定义的。 namespace std _GLIBCXX_VISIBILITY(default) { struct __allocator_traits_...
  • Symfony特质 很少有辅助功能可以在Symfony中更快地开发API 形式特质 handleJSONForm POST , PUT或PATCH请求内容中发送的JSON数据的控制器辅助方法 一般来说,对于带有JS框架的CRUD,发送JSON内容比表单更灵活。...
  • C++ traits

    2017-03-31 19:58:45
    想写一篇C++ traits方面的文章已经有一段时间了,但是说实话traits这项技术确实有些晦涩,很担心写完了达不到期望的效果,于是每每试图以简炼的文字表达,慢慢的就等到了今天。 先说说我为什么专门对这项技术写一篇...
  • c++ traits技法理解

    2020-01-06 17:19:32
    终于理解了c++ traits技法,不得不说它对c++的作用可以说是很大,让编程效率可以提升很多,为什么这多说,就是当我们在写了一个模板后,traits技法可以让这个模板的通用性更强,模板偏特化就会在模板泛化中再设计一...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,504
精华内容 12,201
关键字:

traits