MST

星途 面试题库

面试题:C++ 类模板元编程与类型萃取应用

使用 C++ 类模板元编程实现一个类型萃取工具,能够判断一个给定类型是否为整数类型。如果是整数类型,进一步判断是有符号整数还是无符号整数,并根据判断结果进行不同的编译期操作(例如,对于有符号整数,编译期计算其最大值;对于无符号整数,编译期计算其最小值)。请写出完整的代码实现,并解释代码中每个部分的作用和原理。
30.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <limits>

// 模板元编程:判断类型是否为整数类型
template <typename T>
struct IsInteger {
    static const bool value = false;
};

// 特化模板,判断有符号整数类型
template <>
struct IsInteger<char> {
    static const bool value = true;
};

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

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

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

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

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

// 特化模板,判断无符号整数类型
template <>
struct IsInteger<unsigned char> {
    static const bool value = true;
};

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

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

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

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

// 模板元编程:根据整数类型进行不同编译期操作
template <typename T>
struct IntegerTrait {
    static void operate() {
        static_assert(!IsInteger<T>::value, "T must be an integer type.");
    }
};

// 特化模板,对于有符号整数类型,编译期计算最大值
template <typename T>
struct IntegerTrait<T, std::enable_if_t<std::is_signed<T>::value && IsInteger<T>::value, int> = 0> {
    static void operate() {
        std::cout << "This is a signed integer. Max value: " << std::numeric_limits<T>::max() << std::endl;
    }
};

// 特化模板,对于无符号整数类型,编译期计算最小值
template <typename T>
struct IntegerTrait<T, std::enable_if_t<std::is_unsigned<T>::value && IsInteger<T>::value, int> = 0> {
    static void operate() {
        std::cout << "This is an unsigned integer. Min value: " << std::numeric_limits<T>::min() << std::endl;
    }
};

int main() {
    IntegerTrait<int>::operate();
    IntegerTrait<unsigned long>::operate();
    IntegerTrait<float>::operate(); // 这会触发 static_assert 错误
    return 0;
}

代码解释

  1. IsInteger 模板
    • 这是一个基础模板,用于判断一个类型是否为整数类型。它的默认实现 static const bool value = false; 表示对于一般类型,默认认为不是整数类型。
    • 然后通过特化模板,针对所有有符号和无符号整数类型,将 value 设置为 true,表示这些类型是整数类型。
  2. IntegerTrait 模板
    • 这是一个主模板,当传入的类型不是整数类型时,会触发 static_assert(!IsInteger<T>::value, "T must be an integer type.");,提示错误。
    • 第一个特化模板 IntegerTrait<T, std::enable_if_t<std::is_signed<T>::value && IsInteger<T>::value, int> = 0>
      • std::enable_if_t<std::is_signed<T>::value && IsInteger<T>::value, int> 是一个 SFINAE(Substitution Failure Is Not An Error) 工具,用于有条件地启用模板实例化。只有当 T 是有符号整数类型时,这个特化模板才会被实例化。
      • 在这个特化模板的 operate 函数中,输出有符号整数类型的最大值。
    • 第二个特化模板 IntegerTrait<T, std::enable_if_t<std::is_unsigned<T>::value && IsInteger<T>::value, int> = 0>
      • 同样使用 SFINAE 工具,只有当 T 是无符号整数类型时,这个特化模板才会被实例化。
      • 在这个特化模板的 operate 函数中,输出无符号整数类型的最小值。
  3. main 函数
    • IntegerTrait<int>::operate(); 调用针对有符号整数 int 的特化模板,输出 int 类型的最大值。
    • IntegerTrait<unsigned long>::operate(); 调用针对无符号整数 unsigned long 的特化模板,输出 unsigned long 类型的最小值。
    • IntegerTrait<float>::operate(); 尝试调用针对 float 类型的模板,由于 float 不是整数类型,会触发 static_assert 错误。