MST

星途 面试题库

面试题:C++ 中 SFINAE 如何在模板调试时排除特定类型

假设有一个模板函数 `template <typename T> void func(T t)`,希望在 `T` 为 `std::string` 类型时,不参与函数重载决议(即使用 SFINAE 机制排除 `std::string` 类型),请写出实现代码,并简要解释 SFINAE 在此处的工作原理。
21.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <type_traits>
#include <string>

template <typename T,
          typename = std::enable_if_t<!std::is_same_v<T, std::string>>>
void func(T t) {
    std::cout << "func called with non - std::string type" << std::endl;
}

// 测试
int main() {
    func(10);
    func(3.14f);
    // func(std::string("test")); // 这行代码会导致编译错误
    return 0;
}

SFINAE 工作原理解释

  1. std::enable_if:这是 SFINAE 机制中的关键工具。std::enable_if 是一个类型特性模板,它接受两个参数,第一个是一个布尔值,第二个是一个默认类型(通常为 void)。
  2. 条件判断std::is_same_v<T, std::string> 用于判断类型 T 是否为 std::stringstd::enable_if_t<!std::is_same_v<T, std::string>> 表示当 T 不是 std::string 类型时,std::enable_if 的第一个模板参数为 true,此时 std::enable_if 的第二个模板参数(即 void)会被推导出来。
  3. 函数模板重载决议:在函数模板重载决议过程中,如果某个函数模板的模板参数推导不出来(例如 Tstd::string 时,std::enable_if_t<!std::is_same_v<T, std::string>> 无法推导出类型,因为条件为 false),那么这个函数模板就不会参与重载决议,就好像这个函数模板不存在一样,从而实现了排除 std::string 类型的目的。