C++ traits

 

定义

traits是一种用于泛型编程(Generic Programming)技术, 允许程序根据类型特征进行编译期决策

traits可以在编译时查询和操作类型属性, 而无需在运行时进行类型检查, 通常用于模板编程中以增强代码灵活性和可重用性

例如可以创建一个traits来确定类型是否为某种类型(如整数、浮点数、指针等), 是否满足某种条件(如可复制、可移动), 或者是否具备某种操作(如算术操作、输入输出操作)等

实现

traits通常以模板类形式实现, 并使用模板特化(Template Specialization)来定义特定类型特性

is_same

std::is_same 是C++标准库中所提供traits, 用于判断两个类型是否相同

#include <iostream>
#include <type_traits>

template <typename T>
void CheckType() {
    if (std::is_same<T, int>::value) {
        std::cout << "type is int" << std::endl;
    } else {
        std::cout << "type is not int" << std::endl;
    }
}

int main() {
    CheckType<int>();
    CheckType<double>();
    return 0;
}

自定义Traits类

可以自定义traits类来检查某个类型, 通常使用模板特化来对特定类型进行处理

#include <iostream>
#include <type_traits>

// 默认情况下, 非整数类型
template <typename T>
struct IsInteger {
    static const bool value = false;
};

// 针对整数类型进行特化
template <>
struct IsInteger<int> {
    static const bool value = true;
};

template <>
struct IsInteger<long> {
    static const bool value = true;
};

template <typename T>
void CheckIntegerType() {
    if (IsInteger<T>::value) {
        std::cout << "type is integer" << std::endl;
    } else {
        std::cout << "type is not integer" << std::endl;
    }
}

int main() {
    CheckIntegerType<int>();
    CheckIntegerType<double>();
    return 0;
}

上面代码中, 定义了一个 IsInteger traits 类

通过模板特化将 IsInteger<int>IsInteger<long> 设置为 true, 而其他类型默认为 false

示例

template<class T>
typename iterator_traits<T>::value_type func(T ite) {
    return *ite;
}
  • 模板声明

template 表示 func 是一个模板函数, 可以接受任意类型 T 参数

  • 返回类型 typename iterator_traits::value_type

这是函数返回类型, 使用 iterator_traits 提取 T 类型所对应迭代器值类型(即 value_type)

typename 关键字用于指明 iterator_traits::value_type 是一个类型(type), 而不是一个静态成员或其他内容

  • 参数 T ite

该函数接受一个类型为 T 参数 ite, 通常是一个迭代器(例如指向容器指针或迭代器)

  • 函数体 return *ite;

函数返回 *ite, 即传入迭代器所指向值, 意味着 T 必须是一个可以解引用迭代器类型

iterator_traits

iterator_traits 是一个标准库模板类, 用于萃取迭代器相关类型信息

它主要定义了几个类型别名:value_type、difference_type、pointer、reference 等

iterator_traits::value_type 用于获取迭代器 T 所指向值类型

例如, 若 T 是 std::vector::iterator, 那么 iterator_traits::value_type 将是 int

typename 使用

在 C++ 中, typename 关键字用于消除编译器二义性, 其显式说明后面名称是一个类型(type)

由于 iterator_traits::value_type 是一个依赖于模板参数 T 的嵌套类型, 所以必须在它前面加上 typename 以便正确解析

函数用途

该函数接受一个迭代器 ite, 并返回迭代器解引用后值

返回类型是 T 所对应迭代器 value_type, 这确保了返回值类型与 ite 所指向对象类型相匹配

因此, 该函数可以处理任意迭代器, 例如 std::vecto<int>::iterator、std::list<std::string>::iterator 等, 而不需要知道具体容器类型

#include <iostream>
#include <vector>
#include <iterator>

template<class T>
typename std::iterator_traits<T>::value_type func(T ite) {
    return *ite;
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto it = vec.begin();
    int val = func(it);
    std::cout << "The value is: " << val << std::endl;
    return 0;
}