[转载]__type_traits

本文介绍了C++ STL中traits编程技巧的应用,通过定义结构体或类,为不同类型赋予特性,实现同种操作因类型不同而异的效果。文章详细展示了__type_traits的具体实现及如何根据不同类型进行特化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在STL中为了提供通用的操作而又不损失效率,我们用到了一种特殊的技巧,叫traits编程技巧。具体的来说,traits就是 通过定义一些结构体或类,并利用模板类特化和偏特化的能力,给类型赋予一些特性,这些特性根据类型的不同而异。在程序设计中可以使用这些traits来判 断一个类型的一些特性,引发C++的函数重载机制,实现同一种操作因类型不同而异的效果。traits的编程技巧极度弥补了C++语言的不足 。


举例:

现在定义一个__type_traits可以获得类型的如下属性:
1. 是否存在non-trivial default constructor 
2. 是否存在non-trivial copy constructor
3. 是否存在non-trivial assignment operator
4. 是否存在non-trivial destructor

struct __true_type {
};
struct __false_type {
};

template <class _Tp>
struct __type_traits {

   typedef __false_type    has_trivial_default_constructor;
   typedef __false_type    has_trivial_copy_constructor;
   typedef __false_type    has_trivial_assignment_operator;
   typedef __false_type    has_trivial_destructor;
};


问题:为什么把对象的所有的属性都定义为__false_type?
这样是采用最保守的做法,先把所有的对象属性都设置为__false_type,然后在针对每个基本数据类型设计特化的__type_traits,就可以达到预期的目的,如可以定义__type_traits<int>如下:

template <>
struct __type_traits<int> {
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type    has_trivial_copy_constructor;
   typedef __true_type    has_trivial_assignment_operator;
   typedef __true_type    has_trivial_destructor;
};

template <>
struct __type_traits<char> {
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type    has_trivial_copy_constructor;
   typedef __true_type    has_trivial_assignment_operator;
   typedef __true_type    has_trivial_destructor;
};

    ......

    ......


其他基本类型的traits也可以有相应的定义

__type_traits的偏特化版本
template <class _Tp>
struct __type_traits<_Tp*> {
   typedef __true_type    has_trivial_default_constructor;
   typedef __true_type    has_trivial_copy_constructor;
   typedef __true_type    has_trivial_assignment_operator;
   typedef __true_type    has_trivial_destructor;
   typedef __true_type    is_POD_type;
};

我们可以自定义__type_traits的特化版本
比如对与自定义的Shape类型,我们可以这样定义__type_traits<Shape>
struct __type_traits<Shape> {
   typedef __false_type    has_trivial_default_constructor;
   typedef __true_type    has_trivial_copy_constructor;
   typedef __true_type    has_trivial_assignment_operator;
   typedef __true_type    has_trivial_destructor;
   typedef __true_type    is_POD_type;
};

如果编译器够厉害,我们甚至可以不用自己去定义特化的__type_traits,编译器就能够帮我们搞定:)

如何使用呢?

假设现在用个模板函数fun需要根据类型T是否有non-trivial constructor来进行不同的操作,可以这样来实现:

template<class T>
void fun()
{
     typedef typename __type_traits<T>::has_trivial_constructor _Trivial_constructor;
    __fun(_Trivial_constructor()); // 根据得到的_Trivial_constructor来调用相应的函数
}

// 两个重载的函数
void _fun(_true_type)
{
cout<<"fun(_true_type)called"<<endl;
}
void _fun(_false_type)
{
cout<<"fun(_false_type) called"<<endl;
}

//测试代码

int main()
{
fun<char>();
fun<int>();
fun<char *>();
fun<double>();
}

转载于:https://www.cnblogs.com/ransw/p/3951800.html

### C++ 中 `type_traits` 的使用方法及示例 #### 基本概念 `<type_traits>` 是 C++ 标准库的一部分,提供了一组模板类来查询和操作类型属性。这些工具允许程序员在编译期执行复杂的类型检查、转换和其他元编程任务。 #### 类型特征检测 通过 `<type_traits>` 可以轻松实现不同类型特性的检测。例如: - 判断两个类型的相等性可以利用 `std::is_same<T,U>::value` 来完成[^1]。 ```cpp #include <iostream> #include <type_traits> template <typename T> void checkType() { if (std::is_same<T, int>::value) { std::cout << "T type is int\n"; } else { std://cout << "T type is not int\n"; } } ``` 此代码片段展示了如何基于传递给模板参数的具体类型做出不同行为的选择。 #### 添加额外功能 除了简单的类型比较外,还可以做更多事情,比如验证某个类型是否有特定成员函数或数据成员存在。这通常涉及到 SFINAE 技术的应用[^3]。 定义宏辅助创建自定义类型特质如下所示: ```cpp #define DEFINE_TYPE_TRAIT(name, func)\ template<typename T>\ struct name {\ template<typename Class> \ static constexpr bool test(decltype(&Class::func)*);\ template<typename> \ static constexpr bool test(...);\ \ static constexpr bool value = test<T>(0);\ };\ // 定义具体实例化版本 DEFINE_TYPE_TRAIT(has_func_foo, foo) int main(){ struct A{}; struct B{ void foo(); }; std::cout<<has_func_foo<A>::value<<"\n"; // 输出 0 表明A没有foo() std::cout<<has_func_foo<B>::value<<"\n"; // 输出 1 表明B有foo() return 0; } ``` 这段程序说明了怎样构建自己的类型特性测试器,并应用于实际场景之中。 #### 高级应用案例 当结合其他 STL 组件一起工作时,`type_traits` 更加体现出其强大之处。考虑下面的例子,在容器内部迭代过程中动态调整元素大小: ```cpp #include <vector> #include <string> #include <memory> #include <type_traits> template<class Container> auto resizeElements(Container& c, size_t newSize){ using ValueType=typename Container::value_type; if constexpr(std::is_pointer_v<ValueType>){// 如果是智能指针或其他指向对象的原始指针,则不改变它们所指向的对象尺寸 // Do nothing since we don't want to modify what pointers point at. }else{ for(auto&& elem : c){ if constexpr(!std::is_void_v<std::decay_t<decltype(*elem)>> && !std::is_array_v<std::decay_t<decltype(*elem)>>){ *elem.resize(newSize); } } } } int main(){ std::vector<std::unique_ptr<int[]>> vecPtrs={new int[5], new int[7]}; std::vector<std::string> vecStrings={"hello", "world"}; resizeElements(vecPtrs, 8); // 不会修改数组长度 resizeElements(vecStrings, 10); return 0; } ``` 这里展示了一个通用化的 `resizeElements()` 函数,它可以处理多种情况下的容器内元素重设逻辑,而无需担心破坏原有结构的数据一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值