背景

编码时需要根据传入的类是否包含特定的成员函数来执行不同的分支,经过检索后发现可以对 public 的成员变量和成员函数进行判断。

使用方法

判断类是否存在成员变量

写一个判断是否存在 public 成员函数 AAA 的判定模板方法:

#include <type_traits>
 
template<typename T, typename U = void>
struct check_class_has_var_AAA : std::false_type {};
template<typename T>
struct check_class_has_var_AAA<T, decltype(void(T::AAA), std::declval<T>(), void())> : std::true_type {};

如果需要方便使用,建议使用宏包一下:

#define DECLEAR_CHECK_CLASS_HAS_VAR(VAR_NAME)                                                                         \
    template <typename T, typename U = void>                                                                          \
    struct check_class_has_var_##VAR_NAME : std::false_type                                                           \
    {                                                                                                                 \
    };                                                                                                                \
    template <typename T>                                                                                             \
    struct check_class_has_var_##VAR_NAME<T, decltype(void(T::VAR_NAME), std::declval<T>(), void())> : std::true_type \
    {                                                                                                                 \
    };

使用示例:

#include <iostream>
#include <type_traits>
 
#define DECLEAR_CHECK_CLASS_HAS_VAR(VAR_NAME)                                                                         \
    template <typename T, typename U = void>                                                                          \
    struct check_class_has_var_##VAR_NAME : std::false_type                                                           \
    {                                                                                                                 \
    };                                                                                                                \
    template <typename T>                                                                                             \
    struct check_class_has_var_##VAR_NAME<T, decltype(void(T::VAR_NAME), std::declval<T>(), void())> : std::true_type \
    {                                                                                                                 \
    };
 
DECLEAR_CHECK_CLASS_HAS_VAR(AAA);
DECLEAR_CHECK_CLASS_HAS_VAR(BBB);
 
class TestAAA
{
public:
    int AAA;
};
 
class TestBBB
{
public:
    int BBB;
};
 
int main(int argc, char const *argv[])
{
    std::cout << "class TestAAA::AAA " << check_class_has_var_AAA<TestAAA>::value << std::endl;
    std::cout << "class TestAAA::BBB " << check_class_has_var_BBB<TestAAA>::value << std::endl;
    std::cout << "class TestBBB::AAA " << check_class_has_var_AAA<TestBBB>::value << std::endl;
    std::cout << "class TestBBB::BBB " << check_class_has_var_BBB<TestBBB>::value << std::endl;
    return 0;
}

输出结果为:

vscode ➜ /workspaces/cpp $ ./test.out 
class TestAAA::AAA 1
class TestAAA::BBB 0
class TestBBB::AAA 0
class TestBBB::BBB 1

判断类是否存在成员函数

和变量类似,这里就直接写宏和示例:

#define DECLEAR_CHECK_CLASS_HAS_FUNC(FUNC_NAME)                                                                       \
    template <typename T, typename U = void>                                                                          \
    struct check_class_has_func_##FUNC_NAME : std::false_type                                                         \
    {                                                                                                                 \
    };                                                                                                                \
    template <typename T>                                                                                             \
    struct check_class_has_func_##FUNC_NAME<T, std::void_t<decltype(std::declval<T>().FUNC_NAME())>> : std::true_type \
    {                                                                                                                 \
    };

示例:

#include <iostream>
#include <type_traits>
 
#define DECLEAR_CHECK_CLASS_HAS_FUNC(FUNC_NAME)                                                                       \
    template <typename T, typename U = void>                                                                          \
    struct check_class_has_func_##FUNC_NAME : std::false_type                                                         \
    {                                                                                                                 \
    };                                                                                                                \
    template <typename T>                                                                                             \
    struct check_class_has_func_##FUNC_NAME<T, std::void_t<decltype(std::declval<T>().FUNC_NAME())>> : std::true_type \
    {                                                                                                                 \
    };
 
DECLEAR_CHECK_CLASS_HAS_FUNC(AAA);
DECLEAR_CHECK_CLASS_HAS_FUNC(BBB);
 
class TestAAA
{
public:
    void AAA() {}
};
 
class TestBBB
{
public:
    int BBB(int a) { return 0; }
};
 
int main(int argc, char const *argv[])
{
    std::cout << "class TestAAA::AAA " << check_class_has_func_AAA<TestAAA>::value << std::endl;
    std::cout << "class TestAAA::BBB " << check_class_has_func_BBB<TestAAA>::value << std::endl;
    std::cout << "class TestBBB::AAA " << check_class_has_func_AAA<TestBBB>::value << std::endl;
    std::cout << "class TestBBB::BBB " << check_class_has_func_BBB<TestBBB>::value << std::endl;
    return 0;
}
 

输出结果为:

vscode ➜ /workspaces/cpp $ ./test.out 
class TestAAA::AAA 1
class TestAAA::BBB 0
class TestBBB::AAA 0
class TestBBB::BBB 0