代码实现
#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;
}
};
原理解释
- SFINAE(Substitution Failure Is Not An Error):这是一种 C++ 模板元编程技术。当编译器在实例化模板时,如果某个模板参数替换导致了无效的类型或表达式,这并不被视为错误,而是会导致该模板实例化被忽略。
std::enable_if
:这是一个类型特性工具,定义在 <type_traits>
头文件中。它根据一个布尔条件来决定是否定义一个类型。如果条件为真,std::enable_if
会定义一个名为 type
的成员类型;如果条件为假,则 std::enable_if
没有 type
成员类型。
- 在代码中的应用:
- 在
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
时,编译器会根据模板参数的特性,选择合适的版本进行调用。