MST

星途 面试题库

面试题:C++ 复杂场景下 SFINAE 模板选择的应用

假设有一个模板类 `MyClass`,其中有多个模板成员函数。要求根据传入模板参数的不同特性(例如是否为整数类型、是否为指针类型),利用 SFINAE 技术实现不同版本成员函数的合理调用。请写出相关代码实现,并解释其原理。
23.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

代码实现

#include <iostream>
#include <type_traits>

template <typename T>
class MyClass {
public:
    // 针对整数类型的成员函数
    template <typename U = T,
              std::enable_if_t<std::is_integral<U>::value, int> = 0>
    void memberFunction() {
        std::cout << "This is for integral types." << std::endl;
    }

    // 针对指针类型的成员函数
    template <typename U = T,
              std::enable_if_t<std::is_pointer<U>::value, int> = 0>
    void memberFunction() {
        std::cout << "This is for pointer types." << std::endl;
    }
};

原理解释

  1. SFINAE(Substitution Failure Is Not An Error):这是一种 C++ 模板元编程技术。当编译器在实例化模板时,如果某个模板参数替换导致了无效的类型或表达式,这并不被视为错误,而是会导致该模板实例化被忽略。
  2. std::enable_if:这是一个类型特性工具,定义在 <type_traits> 头文件中。它根据一个布尔条件来决定是否定义一个类型。如果条件为真,std::enable_if 会定义一个名为 type 的成员类型;如果条件为假,则 std::enable_if 没有 type 成员类型。
  3. 在代码中的应用
    • MyClass 类的 memberFunction 模板函数中,使用了 std::enable_if 作为模板参数。例如,std::enable_if_t<std::is_integral<U>::value, int> = 0,这里 std::is_integral<U>::value 用于判断 U 是否为整数类型。如果是整数类型,std::enable_if_t 会产生一个 int 类型(因为第二个模板参数是 int),模板实例化有效;如果不是整数类型,模板实例化会失败,但由于 SFINAE 规则,这不会导致编译错误,只是该版本的 memberFunction 会被忽略。
    • 同理,std::enable_if_t<std::is_pointer<U>::value, int> = 0 用于判断 U 是否为指针类型,从而决定对应的 memberFunction 版本是否参与重载决议。这样,当调用 MyClass 对象的 memberFunction 时,编译器会根据模板参数的特性,选择合适的版本进行调用。