我刚刚创建了一个模板来检测类的数据成员是否是静态定义的。在这篇文章中,成员的可访问性不是它应该关注的(假设成员总是可以通过模板访问)。以下是包含任何测试符号的代码:
#include <conio.h>
//#include <stdio.h>
#include <iostream>
struct A1
{
int a;
};
struct A2
{
static int a;
};
int A2::a{};
template < class My_Type >
struct TestStatic
{
template < typename raw_ty > static char fTest(...);
template < typename class_ty, typename arg_ty = decltype(class_ty::a) >
static int fTest(int, arg_ty & = class_ty::a);
enum nRes { result = sizeof(fTest<My_Type>(0)) - 1 };
};
int main(void)
{
int i;
i = TestStatic<A1>::result;
std::cout << i << std::endl;
i = TestStatic<A2>::result;
std::cout << i << std::endl;
_getch();
return(0);
}
问题是,当它使用g ++ 4.8构建时,编译通过但得到的结果是两个'3'而不是一个'0'和另一个'3'。有什么不对吗?
答案 0 :(得分:4)
您的方法存在根本缺陷,因为decltype(T::x)
is perfectly valid for non-static
members:
#include <iostream>
struct T
{
int x;
};
int main()
{
std::cout << sizeof(decltype(T::x)) << '\n';
}
// Output: 4
您可get what you want使用std::is_member_pointer
:
如果
T
是指向非静态成员对象的指针或指向非静态成员函数的指针,则提供等于true
的成员常量值。对于任何其他类型,值为false
。
#include <iostream>
#include <type_traits>
struct T
{
int x;
};
struct S
{
static int x;
};
int main()
{
std::cout << !std::is_member_pointer<decltype(&T::x)>::value << ' ';
std::cout << !std::is_member_pointer<decltype(&S::x)>::value << '\n';
}
// Output: 0 1
这是有效的,因为只有当成员不是::
时才通过static
语法访问成员才会生成指向成员的指针。当成员为static
时,它当然是正常的变量访问。