将模板类型限制为基类而不是基类的子类,可以使用模板元编程技术中的类型萃取(type traits)来实现。
类型萃取是一种在编译期间获取类型信息的技术,它可以通过模板特化和SFINAE(Substitution Failure Is Not An Error)原则来判断一个类型是否是另一个类型的子类。
以下是一种实现方式:
#include <type_traits>
template <typename Base, typename Derived>
struct is_base_of {
private:
template <typename T>
static std::true_type test(const Base*);
template <typename T>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<Derived>(nullptr))::value;
};
template <typename Base, typename Derived>
constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;
使用上述代码,可以通过 is_base_of_v<Base, Derived>
来判断 Derived
是否是 Base
的子类。如果返回值为 true
,则说明 Derived
是 Base
的子类,可以进行模板实例化;如果返回值为 false
,则说明 Derived
不是 Base
的子类,编译器会报错。
以下是一个示例:
#include <iostream>
class Base {
public:
virtual void foo() {
std::cout << "Base::foo()" << std::endl;
}
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived::foo()" << std::endl;
}
};
template <typename T, typename = std::enable_if_t<is_base_of_v<Base, T>>>
void bar(T& obj) {
obj.foo();
}
int main() {
Base base;
Derived derived;
bar(base); // 输出:Base::foo()
bar(derived); // 输出:Derived::foo()
return 0;
}
在上述示例中,bar
函数使用了类型萃取技术,将模板类型限制为 Base
的子类。当传入的对象是 Base
或其子类时,bar
函数可以正常调用;当传入的对象不是 Base
或其子类时,编译器会报错。
这种方式可以在编译期间进行类型检查,避免了在运行时出现类型错误的情况。同时,它也提供了更好的代码可读性和可维护性。
领取专属 10元无门槛券
手把手带您无忧上云