模板就把他当成:我们定义一个模板,他用来表示类型,函数或者类<>跟的是指定类型
类型就是比如 int ,long,char,类,结构体等
模板的主要目的:同一个类,函数可以调用不同类型的参数。
#pragma once #include <type_traits>
//FUNCTOR_TYPEDEF这个宏就相当于:
//FUNCTOR_TYPEDEF(name, 类型一, 类型二) ========typedef Functor<rettype, 类型一, 类型二> name
意思就是定义一个class Functor的类型,名叫name(就好比: typedef unsigned int u32;),为class Functor注入模块<rettype, 类型一, 类型二>。。模块对应的定义是在template <class RetType, class... Args>//----------------------------------------------------------------<模板一>
#define FUNCTOR_TYPEDEF(name, rettype, ...) \ typedef Functor<rettype, ## __VA_ARGS__> name//定义一个对象
#define FUNCTOR_DECLARE(name, rettype, ...) \
Functor<rettype, ## __VA_ARGS__> name//Functor<rettype, ## __VA_ARGS__>::bind<std::remove_reference<decltype(*obj)>::type, func>(obj)
//其实里面的尖括号可以先去掉,Functor::bind(obj)其实就是调用的类Functor里面的bind静态函数。
//因为bind也是有模板的(对应--------------------------------------------<模板二>),所以也用<>来带入类型。
//decltype获得变量的类型,
//std::remove_reference为C++0x标准库中的元函数,其功能为去除类型中的引用。 //std::remove_reference<U&>::type <=> U //std::remove_reference<U&&>::type <=> U //std::remove_reference<U>::type <=> U
#define FUNCTOR_BIND(obj, func, rettype, ...) \
Functor<rettype, ## __VA_ARGS__>::bind<std::remove_reference<decltype(*obj)>::type, func>(obj) #define FUNCTOR_BIND_MEMBER(func, rettype, ...) \ Functor<rettype, ## __VA_ARGS__>::bind<std::remove_reference<decltype(*this)>::type, func>(this) template <class RetType, class... Args>//----------------------------------------------------------------<模板一> class Functor { public: constexpr Functor(void *obj, RetType (*method)(void *obj, Args...)) : _obj(obj) , _method(method) { } // Allow to construct an empty Functor constexpr Functor(decltype(nullptr)) : Functor(nullptr, nullptr) { } constexpr Functor() : Functor(nullptr, nullptr) { } // Call the method on the obj this Functor is bound to RetType operator()(Args... args) const { return _method(_obj, args...); } // Compare if the two Functors are calling the same method in the same // object inline bool operator==(const Functor<RetType, Args...>& rhs) { return _obj == rhs._obj && _method == rhs._method; } // Allow to check if there's a method set in the Functor explicit operator bool() const { return _method != nullptr; } // T::*method表示method必须是类型T里面定义的函数,要调用class里面的函数需要这样定义。 template<class T, RetType ( T::*method)(Args...)>//----------------------------------------------------------------<模板二> static constexpr Functor bind( T *obj){
//这里就是返回一个Functor类型的对象。对象不就是_obj,和method_wrapper函数组成嘛。对应3333那两个参数。
return { obj, method_wrapper<T, method> }; } private: void *_obj;//------------------------------------------------------------------------------------------------------3333 RetType (*_method)(void *obj, Args...);template<class T, RetType (T::*method)(Args...)>//----------------------------------------------------------------(模板三)
//这里才是真正的调用对象注册的方法。
static RetType method_wrapper(void *obj, Args... args)// { T *t = static_cast<T*>(obj); return (t->*method)(args...); } };
编写模板类:
模版本身并不是个定义,当实体化的时候才完成了定义,然后拿这个定义才能去建立对象, 所以放的一起
1.模板类的定义与实现只写在头文件中:
目前主流编译器不支持分离编译,即模板声明写到h文件中,实现写到cpp文件中。 C++标准倒是规定有分离编译,不过对于编译器来说实现比较困难所以大多数编译器不支持(包括vc全系列)
2.如果要将实现写在cpp中需要:
template <typename T> bool Vector3<T>::is_inf(void) const { return isinf(x) || isinf(y) || isinf(z); } template bool Vector3<float>::is_inf(void) const; 对其进行实例化。很麻烦
3.如果模板声明写到h文件中,实现写到cpp文件中。会出现在生成执行文件时,找不到该函数声明"undefined reference to"