traits使用的场景一般有三种 分发到不同处理流程 解决C++代码中某些无法编译的问题
比如一个图书馆的代码,接受书籍并收入到不同类别中
template<class T> // T表示接受的是何种书籍
void AcceptBooks(T books)
{
... //do something
};
我们有不同书籍 历史类书籍和计算机类书籍
struct history_tag{}; //这只是个空类,目的是激发函数重载
struct computer_tag{}; //同上
class HistoryBooks
{
public:
// 类型(身份)标志,表示这是历史类书籍,
// 如果是历史类则为typedef history_tag bookType;
typedef history_tag bookType;
};
class ComputerBooks
{
public:
typedef computer_tag bookType;
};
然后在接受书籍的代码里,对于不同类型的书籍进行不同处理
// 第二个参数为无名参数,只是为了激发函数重载
template<typename T>
void Accept(T& t,computer_tag)
{
std::cout << "accept computer books" << std::endl;
}
template<typename T>
void Accept(T& t,history_tag)
{
std::cout << "accept history books" << std::endl;
}
于是先前的AcceptBooks函数可以改写如下:
template<typename T>
void AcceptBooks(T& t)
{
// 无论是accept 历史书籍还是计算机书籍,根据不同的type 进入到不同的accept函数中去了
typedef typename T::bookType bookType;
Accept(t,bookType());
}
当然 进行一些必要的封装 看起来就更像样子了
template<typename T>
struct BooksTraits
{
typedef typename T::bookType bookType;
};
accept函数就写成这样
Accept(t, typename BooksTraits<T>::bookType());
完整代码如下:
#include <iostream> struct history_tag{}; //这只是个空类,目的是激发函数重载 struct computer_tag{}; //同上 class HistoryBooks
{
public:
typedef history_tag bookType;
}; class ComputerBooks
{
public:
typedef computer_tag bookType;
}; template<typename T>
void Accept(T& t,computer_tag)
{
std::cout << "accept computer books" << std::endl;
}
template<typename T>
void Accept(T& t,history_tag)
{
std::cout << "accept history books" << std::endl;
} // template<typename T>
// void AcceptBooks(T& t)
// {
// typedef typename T::bookType bookType;
// Accept(t,bookType());
// } template<typename T>
struct BooksTraits
{
typedef typename T::bookType bookType;
}; template<typename T>
void AcceptBooks(T& t)
{
Accept(t, typename BooksTraits<T>::bookType());
} int _tmain(int argc, _TCHAR* argv[])
{
ComputerBooks cb;
HistoryBooks hb;
AcceptBooks(cb);
AcceptBooks(hb); return 0;
}
一些示例代码
// 123.cpp: 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <type_traits>
#include <iostream> //=======================================================
// is array
template<typename T>
struct is_array {
static const bool value = false;
}; template<typename T,size_t N>
struct is_array < T[N] > {
static const bool value = true;
};
//========================================================= //===========================================================
//is class
typedef char(&yes_type)[]; // sizeof(yes_type)==1
typedef char(&no_type)[]; // sizeof(no_type)==2 template<typename T>
struct is_class_impl {
template<typename U>
static
yes_type is_class_tester(void(U::*)(void)); template<typename U>
static
no_type is_class_tester(...);
static const bool value = (sizeof(is_class_tester<T>()) == sizeof(yes_type));
}; template<typename T>
struct is_class
{
// 所有实现都在is_class_imp中
static const bool value = is_class_impl<T>::value;
}; class testA {};
//============================================================== //============================================================
//is member function pointer //================================================= int main()
{
std::cout << is_array<int>::value << std::endl;
std::cout << is_array<int[]>::value << std::endl;
std::cout << is_array<int[]>::value << std::endl;
std::cout << is_class<int>::value << std::endl;
std::cout << is_class<testA>::value << std::endl;
return ;
}
至于刘未鹏(地址见文章最后参考列表)
所说的traits 用于效率一说 我觉得也算是分发到不同处理流程中的一种使用方法。
解决C++代码中某些无法编译的问题 则是说使用traits避开一些问题
比如引用的引用。
参考:
1 boost源码剖析之:泛型编程精灵type_traits(rev#2) http://blog.csdn.net/pongba/article/details/83828