用模板元编程的方式判断一个结构体是否含有某成员函数

最近在看kdtree的东西找到一个只包含头文件的实现版,看到里面有这样一段代码一脸懵


template <typename T, typename = int> struct has_resize : std::false_type {};

查了一下才知道这个语句是一个用于进行模板元编程的定义。它定义了一个模板结构体 has_resize,该结构体用于判断类型 T 是否拥有 resize 成员函数。

让我们逐步解释这个语句:

template <typename T, typename=int> struct has_resize : std::false_type {};
  • template :这代表着这是一个模板结构体,并接受两个模板参数。第一个参数 T 是待检查的类型,第二个参数 int 是一个默认参数。
  • struct has_resize : std::false_type {}:这定义了一个结构体 has_resize,并继承自 std::false_type 类。std::false_type 是一个标准库中的结构体,用于表示布尔值 false

这段代码的作用是定义了 has_resize 结构体,并将其默认初始化为 std::false_type,意味着默认情况下假设待检查的类型 T 不具有 resize 成员函数。

此时,我们可以使用特化(specialization)来对具体的类型进行判断。如果某个特定类型 T 拥有 resize 成员函数,那么可以创建一个非模板的 has_resize 的部分特化版本,将其继承自 std::true_type 类,从而改变默认的 std::false_typestd::true_type

template <typename T> struct has_resize<T, decltype(std::declval<T>().resize(0), 0)> : std::true_type {};

这个部分特化的定义使用了 SFINAE(Substitution Failure Is Not An Error)机制来根据 T 的属性进行匹配。如果 T 类型在调用表达式 std::declval().resize(0) 时能够通过编译,那么这个部分特化将生效,继承自 std::true_type,表示类型 T 确实具有 resize 成员函数。

通过结合这两部分定义,我们可以在模板元编程中使用 has_resize::value 来判断某个类型 T 是否支持 resize 成员函数。如果 has_resize::valuetrue,则表示类型 T 支持 resize 成员函数;如果为 false,则表示不支持。

例如:

#include 
#include 

template <typename T, typename=int> struct has_resize : std::false_type {};

template <typename T>
struct has_resize<T, decltype(std::declval<T>().resize(0), 0)> : std::true_type {};

class Container {
public:
    void resize(int size) {
        std::cout << "Resizing container to size: " << size << std::endl; 
    }
};

class NoResizeContainer {
    // 没有 resize 成员函数
};

int main() {
    std::cout << std::boolalpha;
    std::cout << has_resize<Container>::value << std::endl;  // 输出 true
    std::cout << has_resize<NoResizeContainer>::value << std::endl;  // 输出 false

    return 0;
}

在上述示例中,has_resize::value 的值为 true,表示 Container 类型具有 resize 成员函数。而 has_resize::value 的值为 false,表示 NoResizeContainer 类型不具有 resize 成员函数。

这种技术可以用于编写更加泛化和灵活的代码,根据类型的特性来进行条件判断和分发。

你可能感兴趣的:(C++,c++,模板元编程)