如何检测类中是否存在特定的成员变量?
为了创建算法模板函数,我需要知道作为模板参数的类中是 x 还是 X(以及 y 或 Y).在将我的函数用于 MFC CPoint 类或 GDI+ PointF 类或其他一些类时,它可能很有用.他们都使用不同的 x .我的解决方案可以简化为以下代码:
For creating algorithm template function I need to know whether x or X (and y or Y) in class that is template argument. It may by useful when using my function for MFC CPoint class or GDI+ PointF class or some others. All of them use different x in them. My solution could be reduces to the following code:
template<int> struct TT {typedef int type;};
template<class P> bool Check_x(P p, typename TT<sizeof(&P::x)>::type b = 0) { return true; }
template<class P> bool Check_x(P p, typename TT<sizeof(&P::X)>::type b = 0) { return false; }
struct P1 {int x; };
struct P2 {float X; };
// it also could be struct P3 {unknown_type X; };
int main()
{
P1 p1 = {1};
P2 p2 = {1};
Check_x(p1); // must return true
Check_x(p2); // must return false
return 0;
}
但它不能在 Visual Studio 中编译,而在 GNU C++ 中编译.使用 Visual Studio,我可以使用以下模板:
But it does not compile in Visual Studio, while compiling in the GNU C++. With Visual Studio I could use the following template:
template<class P> bool Check_x(P p, typename TT<&P::x==&P::x>::type b = 0) { return true; }
template<class P> bool Check_x(P p, typename TT<&P::X==&P::X>::type b = 0) { return false; }
但它不能在 GNU C++ 中编译.有通用的解决方案吗?
But it does not compile in GNU C++. Is there universal solution?
UPD:此处的结构 P1 和 P2 仅用作示例.可能有任何具有未知成员的类.
UPD: Structures P1 and P2 here are only for example. There are could be any classes with unknown members.
附言请不要在此处发布 C++11 解决方案,因为它们很明显且与问题无关.
P.S. Please, do not post C++11 solutions here because they are obvious and not relevant to the question.
推荐答案
另一种方式是这个,它依赖于 SFINAE 表达式.如果名称查找导致歧义,编译器将拒绝模板
Another way is this one, which relies on SFINAE for expressions too. If the name lookup results in ambiguity, the compiler will reject the template
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A { int x; };
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
它基于 usenet 上某人的绝妙想法.
It's based on a brilliant idea of someone on usenet.
注意:HasX 检查任何名为 x 的数据或函数成员,具有任意类型.引入成员名称的唯一目的是使成员名称查找可能存在歧义――成员的类型并不重要.
Note: HasX checks for any data or function member called x, with arbitrary type. The sole purpose of introducing the member name is to have a possible ambiguity for member-name lookup - the type of the member isn't important.
相关文章