SFINAE 遇到问题。我需要能够确定类型是否定义了成员函数 operator-> 而不管其返回类型如何。示例如下。
这个类在测试器中。它定义了返回类型为 X* 的 operator->()。因此,我不知道在任何地方硬编码它是什么“X”。
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
此类尝试确定传入的 T 是否定义了方法 operator->;不管 operator-> 返回类型是什么。
template<typename T>
struct HasOperatorMemberAccessor
{
template <typename R, typename C> static R GetReturnType( R ( C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, decltype( GetReturnType(&U::operator->)), &U::operator-> >*);
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
除了 operator-> return type 必须是 'Object' 之外,这个类与上面的完全相同。
template<typename T>
struct HasOperatorMemberAccessorOBJECT
{
template <typename R, typename C> static R GetReturnType( R ( C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, Object*, &U::operator-> >*); // only change is we hardcoded Object as return type.
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
结果:
void main()
{
HasOperatorMemberAccessor<PointerX<Object>>::Test<PointerX<Object>>(0); // fails ::value is false; Test => Test(...)
HasOperatorMemberAccessorOBJECT<PointerX<Object>>::Test<PointerX<Object>>(0); // works! ::value is true; Test => Test(SFINAE<>*)
}
HasOperatorMemberAccessor 无法找到 PointX 的成员函数“Object operator->() const”。所以它使用Test的通用版本Test(...)。
但是,HasOperatorMemberAccessorOBJECT 能够找到 PointX 的“Object operator->() const”。因此它使用Test 专用版本Test(SFINAE*)。
两者都应该能够找到“Object operator->() const”方法;因此两者都应该使用Test的专用版本Test(SFINAE*);因此 HasOperatorMemberAccessor>::value 对两者都应该为真。
HasOperatorMemberAccessor 和 HasOperatorMemberAccessorOBJECT 之间的唯一区别是 HasOperatorMemberAccessorOBJECT 的类型名 R 硬编码为对象,
所以问题是“decltype(GetReturnType(&U::operator->))”没有正确返回对象。我尝试了许多不同的发现返回类型的许可。他们如下:
decltype( GetReturnType(&U::operator->) )
typename decltype( GetReturnType(&U::operator->))
decltype( ((U*)nullptr)->operator->() )
typename decltype( ((U*)nullptr)->operator->() )
没有工作,为什么?我正在使用 MSVC++ 10.0。