类型萃取

类型萃取

借用化学中的萃取概念,类型萃取即将混合类型中的部分类型提取出来。在C++中可以使用模板实现这个功能。

非类成员变量的类型萃取

对于变量混合类型如 int *const int 等,我们可以将 *const 去掉,只留下 int

template <typename T>
struct remove_pointer;

template <typename T>
struct remove_pointer<T *> {
    using type = T;
};

int main() {
    using type = remove_pointer<int *>::type; //using type = int
    return 0;
}
template <typename T>
struct remove_const;

template <typename T>
struct remove_const<const T> {
    using type = T;
};

int main() {
    using type = remove_const<const int>::type; //using type = int
    return 0;
}

对于上面两段代码,我们先声明了一个类模板,然后将这个类模版进行偏特化,这样就能使得特定的类型匹配这个模板的偏特化,从而将部分类型萃取出来。

非类成员函数的类型萃取

对于一个函数,我们可以使用类型萃取将它的返回值类型,参数类型提取出来。

假设我们有一个函数,它有一个参数

bool Foo(int) {
    return true;
}

我们可以用通过函数指针,用类似的的方法萃取函数的返回值类型和参数类型。

template <typename T>
struct function_traits;

template <typename Ret, typename Param>
struct function_traits<Ret (*)(Param)> {
    using ret_type = Ret;
    using param_type = Param;
};

int main() {
    using function_info = function_traits<decltype(&Foo)>;
    using ret = function_info::ret_type; //using ret = bool
    using param = function_info::param_type; //using param = int
    return 0;
}

若函数有不止一个参数,可以使用变长参数模板

bool Foo(int, double, bool) {
    return true;
}

template <typename T>
struct function_traits;

template <typename Ret, typename... Args>
struct function_traits<Ret (*)(Args...)> {
    using ret_type = Ret;
    using param_type = std::tuple<Args...>;
};

int main() {
    using function_info = function_traits<decltype(&Foo)>;
    using ret = function_info::ret_type; //using ret = bool
    using param = function_info::param_type; //using param = std::tuple<int, double, bool>
    return 0;
}

类成员的类型萃取

对于一个类,带有成员变量和成员函数,由于类的成员的指针的特殊性,我们不能直接用上面的方法进行类型萃取,需要在模板的类型参数中额外记录类的信息。

比如,我们有下面的类

struct Person {
    bool IsFemale(int) { return true; };
    float height;
};

这个类中既有成员函数 IsFemale ,还有成员变量 height ,我们如何从类中萃取成员的类型信息?

template <typename T>
struct function_traits;

template <typename T>
struct variable_traits;

template <typename Ret, typename Class, typename Param>
struct function_traits<Ret (Class::*)(Param)> {
    using ret_type = Ret;
    using class_type = Class;
    using param_type = Param;
};

template <typename Type, typename Class>
struct variable_traits<Type(Class::*)> {
    using type = Type;
    using class_type = Class;
};

int main() {
    using function_info = function_traits<decltype(&Person::IsFemale)>;
    using function_ret = function_info::ret_type; //using function_ret = bool
    using function_param = function_info::param_type; //using function_param = int

    using variable_info = variable_traits<decltype(&Person::height)>;
    using variable_type = variable_info::type; //using variable_type = float
    return 0;
}

因为类的成员指针类型为 Class::* ,所以在模板中也要改成相应的格式。

以上就是类型萃取的方法,该方法在构建反射系统中有重要的作用。

posted @ 2024-08-27 20:55  imyhy  阅读(71)  评论(0)    收藏  举报