如何检测class中是否存在特定的PRIVATE成员变量?
How to detect whether there is a specific PRIVATE member variable in class?
此问题基于this post。
目标: 我想知道一个class是否有成员变量x
。无论此变量是 private
、public
还是 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::x
的 friend
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
继承自T
和check_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;
}
此解决方案的缺点:当 T
将 x
声明为方法或 using
类型时,decltype(U::x)
也会失败(歧义)。所以给出
class foo
{ int x () { return 0;} ; };
或
class foo
{ using x = int; };
从 check_x<foo>::value
你获得 1
.
此问题基于this post。
目标: 我想知道一个class是否有成员变量x
。无论此变量是 private
、public
还是 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::x
的 friend
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
继承自T
和check_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;
}
此解决方案的缺点:当 T
将 x
声明为方法或 using
类型时,decltype(U::x)
也会失败(歧义)。所以给出
class foo
{ int x () { return 0;} ; };
或
class foo
{ using x = int; };
从 check_x<foo>::value
你获得 1
.