类型特征:检查引用成员变量是否是静态的
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");
活生生的例子。
我理解错误,指针不能指向引用成员。但是如何避免它,并且仍然区分它是静态变量还是非静态变量?你知道吗?
如果&E::foo
使用SFINAE失败,您可以添加一个回退(如果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
只是在T::foo
无效的情况下"让SFINAE"回退到第三个重载,但由于使用了逗号运算符,结果类型为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_
函数),请参阅以下两个答案:
- https://stackoverflow.com/a/36694627/2666289
- https://stackoverflow.com/a/36693801/2666289
相关文章:
- 如何检查变量是否是C++中的地图?
- 使用类在C++中存储和列出变量/方法是否是一种好的做法
- "new"创建的实例的所有成员变量是否都存在于堆上而不是堆栈上?
- 有没有办法检查发送到变量的值是否是正确的类型,而它已经在该变量下?
- 检查C++中是否只有一个字符串变量不是 nullptr
- 为许多类可能需要的所有常量变量制作独立的头文件是否是一种很好的做法?
- 如何判断变量是否是一个复杂的数字C
- C++ - 在类中包含不是类对象属性的变量是否是一种不好的做法
- 不可变的 lambda 函数:复制捕获的变量是否允许是 const
- 我怎么知道内存中的变量是否是指针
- 确定函数是否是在没有设置全局变量的情况下调用的
- 类型特征:检查引用成员变量是否是静态的
- 如何检测变量是否是犰狳阵列
- 当您将引用返回到局部变量时,它是否是一种未定义的行为
- 有没有办法检查一个变量是否是一个整数?C++
- 如何检查变量是否是std::string类型
- 为将来的'unset'变量定义外部变量是否是一种好的做法?
- 是否有一种工具可以帮助理解谁将特定的参数传递给函数,以及该变量最初是在哪里创建的(在C/ c++中)
- 是否所有全局变量都是volatile限定的?
- 告诉子类对超类的受保护变量执行某些操作是否是一种好的做法(也许是一些已知的设计模式?)?