C++ 模板特化与偏特化

模板特化与偏特化

原则:所有偏特化的时候,template的<>中写的typename在class中必须全部使用,所有class中使用的typename,必须在class<>和template<>中写明!!!!!!!
偏特化主要分两种类型
eg: templateclass;

  1. 指定具体类型,比如T指定为int,则template里需要将T删除,写成templateclass;
  2. 未指定具体类型,但是指定T的相关类型,则template中要保留,写成templateclass;
  3. 当存在可变参数时候,class中必须使用所有的typename,写成templateclass;
    C++ 模板特化与偏特化_第1张图片

模板特化

模板特化(template specialization)不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板特化。模板特化有时也称之为模板的具体化,分别有函数模板特化和类模板特化。

#include 
using namespace std;

template<typename T>class A
{
     
	T num;
public:
	A()
	{
     
		num=T(6.6);
	}
	void print()
	{
     
		cout<<"A'num:"<<num<<endl;
	}
};

template<> class A<char*>
{
     
	char* str;
public:
	A(){
     
		str="A' special definition ";
	}
	void print(){
     
		cout<<str<<endl;
	}
};

int main()
{
     
	A<int> a1;      //显示模板实参的隐式实例化
	a1.print();
	A<char*> a2;    //使用特化的类模板
	A2.print();
}

模板偏特化

模板偏特化(Template Partitial Specialization)是模板特化的一种特殊情况,指显示指定部分模板参数而非全部模板参数,或者指定模板参数的部分特性分而非全部特性,也称为模板部分特化。与模板偏特化相对的是模板全特化,指对所有的模板参数进行特化。模板全特化与模板偏特化共同组成模板特化。

模板偏特化主要分为两种,一种是指对部分模板参数进行全特化,另一种是对模板参数特性进行特化,包括将模板参数特化为指针、引用或是另外一个模板类。

eg1

template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_same           : public false_type {
     };
template <class _Tp>            struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {
     };

is_same函数手动实现,利用偏特化原理

#include 
#include 
template<typename type, type t>
class Type
{
     
    public:
    static constexpr type value = t;
};
class true_type: public Type<bool , true>{
     };
class false_type: public Type<bool , false>{
     };


template<typename type1, typename type2>
class is_same: public false_type
{
     };
template<typename type1>  //模板偏特化
class is_same <type1, type1>: public true_type
{
     };

int main()
{
     
     std::cout<<std::is_same<int,int>::value<<std::endl;
    std::cout<<is_same<int,int>::value<<std::endl;
    

    return 0;
}

eg2

//
//  main.cpp
//  ticketmachine
//
//  Created by Python_liu on 2019/8/6.
//  Copyright © 2019 liuxz. All rights reserved.
//

#include "TicketMachine.hpp"
#include 
#include 
using namespace std;
class type_a
{
     
    public:
        void fun1()
        {
     
            cout<<"world! "<<endl;
        }
};
template<typename T>
class test2
{
     
public:
    void fun2()const
    {
     
        cout<<"wow"<<endl;
    }
    T t;
    
};

template<typename T>
class test1
{
     
public:
    T* operator->();
    using  _test2 = test2<int>;//等价于 typedef test2 _test2!!!
private:
    T a;
    
};
template<typename T>
T* test1<T>::operator->()
{
     
    return &a;
}
template<typename T,class D>//未特化!
class test3
{
     
public:
    void fun3(T num1,D num2)const
    {
     
        cout<<"standard class template"<<endl;
    }
};
template<class D>//偏特化!
class test3<int,D>
{
     
public:
    void fun3(int num1,D num2)
    {
     
        cout<<"partial class template"<<endl;
    }
};
template<typename T,class D>//偏特化!
class test3<T*,D*>
{
     
public:
    void fun3(const T* num1, const D* num2)
    {
     
        cout<<"new partial class template"<<endl;
    }
};
template<>//全特化!
class test3<int,int*>
{
     
public:
    void fun3(const int num1, const int* num2)
    {
     
        cout<<"new partial class template"<<endl;
    }
};
int main(int argc, const char * argv[]) {
     
    // insert code here...
    cout<<"hello"<<endl;
    test1<type_a> h;
    h->fun1();
    test1<type_a>::_test2 k;
    k.fun2();
    typedef int i[5];
    i ii;
    cout<<sizeof(ii)<<endl;
    test3<int,int> b;
    b.fun3(30, 30);//偏特化的优先级高于普通模板!!!!!!
    test3<char,char> c;
    c.fun3('a', 'b');//标准模板的优先级最低!!!
    test3<char*, char*> d;
    d.fun3("haha", "hehe");//全特化的优先级最高!!!
    return 0;
}

模板的特化与偏特化需要注意一下几点:
1、模板是有优先级的,优先级高低是,全特化>偏特化>普通模板
2、偏特化时,template class{};
3、偏特化时,template class{};

易错点

顺序应该是,先把泛化的模板的默认参数补上,然后从上到下进行比较,谁的优先级高就走谁

#include 
#include 
#include 

using namespace std;

 struct GenerateValue
{
     
    using Generated_tag = int;
};
 struct GenerateValue1
{
     
    using Generated_tag = int;
};

template<typename T, typename Tagged = void>
struct has_generated_tag {
     
    static const bool value = true;
    has_generated_tag(){
     cout<<"1111"<<endl;};
};

template<typename T>
struct has_generated_tag<T, typename T::Generated_tag> {
     
     static const bool value = false; // used it type defines an internal type called Generated_tag
     has_generated_tag(){
     cout<<"2222"<<endl;};

};


// C++17-style simplification of syntax.
template<class T>
 bool is_generated_type_v = has_generated_tag<T>::value;

int main()
{
     
    

    cout << "is_generated_type_v: " << is_generated_type_v<GenerateValue> << endl;
    cout << "is_generated_type_v: " << is_generated_type_v<GenerateValue1> << endl;
    cout << "is_generated_type_v: " << is_generated_type_v<string> << endl;
    system("pause");
}
#include 
using namespace std;
template <typename MethodTraits, typename Signature = typename MethodTraits::Signature>
class Method_impl {
     
public:
	Method_impl() {
      cout << "general" <<endl; }
};

template <typename MethodTraits,typename R, typename... Args>
class Method_impl<MethodTraits,R(Args...)> {
     
public:
	Method_impl() {
      cout << "R(Args)" <<endl; }
};

template <typename MethodTraits, typename R>
class Method_impl<MethodTraits, R()> {
     
public:
	Method_impl() {
      cout << "R()" << endl; }
};

template <typename MethodTraits,typename... Args>
class Method_impl<MethodTraits,void(Args...)>{
     
public:
	Method_impl() {
      cout << "void(args)" << endl; }

	void operator()(Args... args) const {
      cout << "()" << endl; }
	void fun1(Args... args) const {
      cout << "[]" << endl; }

};

template <typename MethodTraits>
class Method_impl<MethodTraits, void()>
{
     
public:
	Method_impl() {
      cout << "void()" << endl; }
};
template<typename MethodTraits, typename Signature = typename MethodTraits::Signature>
class Method;

template<typename MethodTraits, typename R , typename... Args>
class Method<MethodTraits, R(Args...)> {
     
private:
	using impl = Method_impl<MethodTraits>;
public:
	Method() :m_impl() {
     };
	void operator()(Args... args) const {
      m_impl(args...); }

	void fun(Args... args) const {
      m_impl.fun1(args...); }
private:
	impl m_impl;
};
struct set_get_value
{
     
	static constexpr int Id{
      1 };

	using Output = double;
	using Signature = Output(int);

};
template<typename... Args>
struct set_value
{
     
	static constexpr int Id{
      2 };

	using Output = void;
	using Signature = Output(Args...);

};

struct other
{
     
	static constexpr int Id{
      2 };

	using Output = void;
	using Signature = void;

};

void testmethod() 
{
     
	Method_impl<set_get_value> method1; //R(args)
	Method_impl<set_get_value, int()> method2; //R()
	Method_impl<set_get_value, int(void)> method3; //R()
	Method_impl<set_get_value, int(int, double)> method8; //general
	Method_impl<set_get_value, void> method4; //general
	Method_impl<set_get_value, void()> method5; //void()
	Method_impl<set_get_value, void(void)> method6; //void()
	Method_impl<set_get_value, void(int)> method7; //void(args)}
}

void testOperator() {
     
	Method<set_value<int,int>> methods;
	int value = 56;
	methods(value,50);
	methods.fun(value,50);

}
template<typename Signature, typename Deserializer>
int deserialize_args(Deserializer& deserializer)
{
     	
	cout << "des"<<deserializer << endl;
	return 0;
}
void testDeserialization()
{
     
	double deserializer = 3.14; 
	auto args = deserialize_args<int()>(deserializer);
}

int main() 
{
     
	testOperator();
	system("pause");
	return 0;
}


你可能感兴趣的:(c++学习)