繁体   English   中英

类型特征:检查引用成员变量是否为静态

[英]Type trait: Check if reference member variable is static or not

我想检查一个类的成员变量是否是静态的。 使用std :: is_member_pointer可以对所有类型(引用成员除外)正常工作。

#include <type_traits>

struct A {
  int foo;
};

struct B : A {};

struct C {
  static int foo;
};

struct D : C {
};

struct E {
  int &foo;
};

struct F {
  static int &foo;
};

static_assert(std::is_member_pointer<decltype(&A::foo)>::value, "No");
static_assert(std::is_member_pointer<decltype(&B::foo)>::value, "No");
static_assert(!std::is_member_pointer<decltype(&C::foo)>::value, "No");
static_assert(!std::is_member_pointer<decltype(&D::foo)>::value, "No");

// Fail to compile:
static_assert(std::is_member_pointer<decltype(&E::foo)>::value, "No");

static_assert(!std::is_member_pointer<decltype(&F::foo)>::value, "No");

现场示例。

我理解错误,即指针无法指向引用成员。 但是如何避免它并仍然区分它是静态变量还是非静态变量? 有什么想法吗?

如果使用SFINAE导致&E::foo失败,您可以添加一个备用(如果根本不存在E::foo则可以添加另一个):

template <typename T>
std::is_member_pointer<decltype(&T::foo)> is_member_foo(int);

template <typename T>
decltype(T::foo, std::true_type{}) is_member_foo(long);

template <typename T>
std::false_type is_member_foo(...);

template <typename T>
using IsMemberFoo = decltype(is_member_foo<T>(0));

static_assert(IsMemberFoo<A>{}, "No");
static_assert(IsMemberFoo<B>{}, "No");
static_assert(!IsMemberFoo<C>{}, "No");
static_assert(!IsMemberFoo<D>{}, "No");
static_assert(IsMemberFoo<E>{}, "No");
static_assert(!IsMemberFoo<F>{}, "No");
static_assert(!IsMemberFoo<G>{}, "No"); // struct G { };

该代码的作用:

  • 如果&T::foo有效,它将使用std::is_member_pointer (您的版本)检查成员是否为静态成员。
  • 如果&T::foo无效,它将回退到第二个重载(此处您可以确定foo不是静态的,否则将选择第一个重载):
    • 如果T::foo有效(成员存在),则返回std::true_type
    • 否则,它会退回到最后一个重载并返回std::false_type

另请注意(由于@iammilind),对于private成员T::foo 无效 ,因此将选择第三个重载。

关于ideone的工作示例: http ://ideone.com/FILHbK

旁注(扩展说明):

  • &T::foo有效时,前两个重载有效,但选择第一个重载是因为int是精确匹配而long不是。
  • decltype(T::foo, std::true_type{}) T::foo是只在这里“让SFINAE”回落到第三个重载如果T::foo是无效的,但产生的类型std::true_type多亏了逗号运算符。

如果您愿意,还可以创建一个通用版本( http://ideone.com/lzH2FB ):

#define IsMember(MEM) \
template <typename T> \
std::is_member_pointer<decltype(&T::MEM)> is_member_##MEM(int); \
template<typename T> \
decltype(T::MEM, std::true_type{}) is_member_##MEM(long); \
template <typename T> \
std::false_type is_member_##MEM(...); \
template <typename T> \
using IsMember_##MEM = decltype(is_member_##MEM<T>(0));

// Instanciate IsMember_foo
IsMember(foo);

// Use it:
static_assert(IsMember_foo<A>{}, "No");

如果要将所有内容封装在一个类中(不具有is_member_函数),也请参见以下两个答案:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM