如何检测class中是否存在特定的PRIVATE成员变量?

How to detect whether there is a specific PRIVATE member variable in class?

此问题基于this post

目标: 我想知道一个class是否有成员变量x。无论此变量是 privatepublic 还是 protected.

,我都希望收到 true

方法:如果class有一个成员变量,可以通过以下代码获取信息:


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

template <typename T>
struct HasX <T, decltype((void) T::x, 0)> : std::true_type { };

一起使用
if constexpr (HasX<my_class>::value) {
   // do stuff with x
} else {
   // ...
}

上面的代码在这种情况下不起作用

struct my_class {
private:
   int x;
};

我怎样才能完成这项工作?我希望 HasX<my_class>::value 成为 true

想法:

使用可以访问 T::xfriend class。这似乎不起作用。看看这个 live example.

以下似乎可行。请告诉我是否需要改进。 Live example.

class Haser {
public:
template <typename T, typename = int>
static constexpr bool HasX = false;

template <typename T> 
static constexpr bool HasX<T, decltype((void) T::x, 0)> = true;
};

struct A { 
private:    
    int x;
    friend Haser;
};

Haser::HasX<A>true.

嗯……不确定这个解决方案的正确性和局限性……但是……

如果您使用 x 可访问元素定义辅助结构

struct check_x_helper
 { int x; };

您可以编写一个模板结构,它继承自 check_x_helper 和您要查看的 class 是否包含 x 成员

template <typename T>
struct check_x : public T, check_x_helper

check_x内你可以如下声明(仅声明:在decltype()内使用)

template <typename U = check_x, typename = decltype(U::x)>
static constexpr std::false_type check (int);

static constexpr std::true_type check (long);

观察第一个,模板一个:当被勾选的class(T)包含一个x成员时,decltype(U::x)是有歧义的,因为x继承自Tcheck_x_helper,所以这个函数被SFINAE舍弃了。

相反,当T不包含x成员时,没有歧义,decltype(U::x)check_x_helper::x的类型(int) 和第一个 check() 函数保持启用状态。

现在你需要的东西是

using type = decltype(check(0));

static constexpr auto value = type::value;

调用check(0)int参数表示对模板版本的偏好)并将检测到的value保存在static constexpr变量中。

下面是一个完整的编译示例

#include <iostream>
#include <utility>

class foo
 { int x; };

struct bar
 { };

struct check_x_helper
 { int x; };

template <typename T>
struct check_x : public T, check_x_helper
 {
   template <typename U = check_x, typename = decltype(U::x)>
   static constexpr std::false_type check (int);

   static constexpr std::true_type check (long);

   using type = decltype(check(0));

   static constexpr auto value = type::value;
 };

int main()
 {
   std::cout << check_x<foo>::value << std::endl;
   std::cout << check_x<bar>::value << std::endl;
 }

此解决方案的缺点:当 Tx 声明为方法或 using 类型时,decltype(U::x) 也会失败(歧义)。所以给出

class foo
 { int x () { return 0;} ; };

class foo
 { using x = int; };

check_x<foo>::value 你获得 1.