检测是否存在私有成员
Detect existence of private member
我想写一个类型trait来检查某个类型是否有成员member
。如果member
是公共,有很多方法可以做到这一点(例如void_t
),其中最简洁的可能是Yakk的can_apply
(最终可以称为std::is_detected
):
struct C {
int member;
};
template <typename T>
using member_type = decltype(&T::member);
template <typename T>
using has_member = can_apply<member_type, T>;
static_assert(has_member<C>{}, "!"); // OK
但是如果成员是private,这个trait就失败了,因为member
上的访问是病态的(我们不是朋友),并且由于访问原因导致的病态和由于这个东西不存在的原因导致的病态之间没有区别:
class D {
int member;
};
static_assert(has_member<D>{}, "!"); // error
是否有一种方法可以在所有访问控制中编写这样的成员检查器?
对于非final非联合类类型确实有一种方法:
namespace detail {
struct P {typedef int member;};
template <typename U>
struct test_for_member : U, P
{
template <typename T=test_for_member, typename = typename T::member>
static std::false_type test(int);
static std::true_type test(float);
};
}
template <typename T>
using test_for_member =
std::integral_constant<bool, decltype(detail::test_for_member<T>::test(0)){}>;
。诀窍是检查对不同基类的查找是否会产生歧义。(class.member.lookup)/2:
成员名查找决定名称的含义(id-expression)在类作用域(3.3.7)中。名称查找可能导致歧义,在在这种情况下,程序是病态的。[…]进行名称查找
请注意,gcc的查找在类型名称说明符s中忽略非类型名称查找时是被破坏的。
您可以创建另一个类MemberBase
, 确实具有该成员,然后子类化这两个类(检查T
和BaseMember
的类)并尝试访问子类的成员。如果T
也有member
成员,那么就会出现歧义问题。
#include <type_traits>
// Yakk's can_apply
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<class...>struct types{using type=types;};
namespace details {
template<template<class...>class Z, class types, class=void>
struct can_apply : std::false_type {};
template<template<class...>class Z, class...Ts>
struct can_apply< Z, types<Ts...>, void_t< Z<Ts...> > >:
std::true_type
{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,types<Ts...>>;
// Main code
class MemberBase {
public:
int member;
};
template<class ToCheck>
class MemberCheck: public ToCheck, public MemberBase {
};
template <typename T>
using member_type = decltype(&T::member);
template <typename T>
using hasnot_member = can_apply<member_type, MemberCheck<T>>;
template <typename T>
using static_not = std::integral_constant<bool, !T::value>;
template <typename T>
using has_member = static_not<hasnot_member<T>>;
// Tests
class A {
int member;
};
class Ap {
public:
int member;
};
class B {
float member;
};
class C {
int member();
};
class D {
};
static_assert(has_member<A>{}, "!"); // ok
static_assert(has_member<Ap>{}, "!"); // ok
static_assert(has_member<B>{}, "!"); // ok
static_assert(has_member<C>{}, "!"); // ok
static_assert(has_member<D>{}, "!"); // fail
然而,这对我来说绝对是一个肮脏的黑客。
相关文章:
- 我们可以访问一个不存在的联盟的成员吗
- 模板化检查是否存在带有参数列表的类成员函数?
- 检测是否存在具有 C++17 的类成员
- "new"创建的实例的所有成员变量是否都存在于堆上而不是堆栈上?
- 为什么即使存在此静态成员,也不会构造它?
- 如何在C++17中使用type_traits检测具有特定名称和签名的函数(NOT类成员)的存在
- 如果模板中存在成员函数指针,如何获取该指针
- 指向类成员函数的指针中存在类型转换错误
- 从模板检查成员函数重载是否存在
- C++基于模板成员的存在进行成员重载
- 为什么我的类成员不存在?
- 模板元图.班级成员的条件存在
- 如果存在具有不同参数的继承成员,为什么对 C++ 结构函数的调用不明确?
- 统一检查成员函数、自由函数和算子是否存在的方式
- 使用成员初始值设定项时 gcc 中可能存在的错误
- 如何检查派生类的可调用成员函数是否存在
- 从向量中擦除元素是否也会擦除元素中存在的所有成员向量
- 调用成员函数,尽管该对象不存在
- 为什么比较和交换操作同时存在免费函数和成员函数?
- 根据成员变量的类型是否存在,有条件地定义该变量